Understanding Linear Regression
I find the best way to understand linear regressions is as recipes for drawing a graph. Let’s start off with an example relevant to my own life: the relationship between temperatures in Celcius and temperatures in Farenheit. There are two important numeric constants to convert back and forth between them:
- Freezing = 0°C = 32°F
- A change of 1°C = 1.8°F
This gives us all of the necessary components for drawing a graph of the relationship between Farenheit and Celcius. First, we know that a line plotting this relationship must cross 0 on the x-axis at 32 on the y-axis, because freezing = 0°C = 32°F.

Next, we know that for 1 every degree we move to the right, we must move up 1.8.

The line, representing this relationship, thus has the formula:
\[
y = 32 + (1.8\times x)
\]
And looks like

This line has the following properties:
- Its Intercept, or where the line crosses 0 on the x-axis, is 32.
- Its Slope, is 1.8 (that is, a change of 1 on the x-axis corresponds to a change in 1.8 on the y-axis)
And, in fact, all lines, including the ones we fit using linear regression, are described in terms of their intercept (where the line crosses 0 on the x-axis) and slope.
But, let’s say you didn’t know the formula to convert back and forth between Celcius and Farenheit. Maybe you weren’t even sure that there was such a formula. And all you had were a bunch of kind of crappy thermometers that gave you both Celcius and Farenheit readings. And maybe the thermometers are kind of hard to read, or the lighting conditions are dark, or you only have limited experience in reading thermometers. In that case, the relationship between Celcius and Farenheit might look a lot more like this:

In this case, you might want to fit a linear regression. A linear regression assumes that the relationship between two variables can be captured using some line, and it tries to estimate the Intercept and Slope of this assumed line.
The way it does this is by trying to find parameters for a line that minimize the “error” or the “residuals” between the observed data, and the line. For example, here are examples of bad lines. The first assumes that all temperatures Celcius are basically 50°F. The other assumes that all temperatures in Farenheit are basically 3\(\times\)C.
Here is a plot of the best-fitting line, that has the smallest average residuals.

There are actually many different ways to figure out what the best line is (remembering that by “line” we really mean the pairing of Intercept and Slope). For example, one really simplistic approach would be just to draw a bunch of different lines, and see which one worked best.

However, there have been some long established methods for solving this problem, at is, for finding the one and truly best Intercept and Slope for a given set of data points.
Idiom
This isn’t R idiom, but stats idiom. Here are some translations for how people describe solving this problem.
- analytic, closed form = “We solved it with complicated math.”
- iterative, stochastic = “We made a bunch of guesses.”
For the sake of finishing the illustration, here is the solution that a linear regression found for this sample data:
Call:
lm(formula = f_observe ~ c_observe, data = temp_df)
Coefficients:
(Intercept) c_observe
39.275 1.382
The model has estimated that the Intercept is \(\approx\) 39 and the slope is \(\approx\) 1.4 . That is to say, based on our “sample”, it thinks 0°C = 39°F, and that every 1°C increase corresponds to a 1.4°F increase.
We are lucky to know that this is, strictly speaking, wrong, but we won’t usually, or typically, be able to in such a situation. However, the estimate of both the intercept and slope have the right sign (that is, it hasn’t guessed the intercept is -10, or the slope goes the other way), and they’re just about the right magnitude (that is, it hasn’t guessed that the slope is something like 10, or 100).
Now, let’s consider how the linear model is describing the value of this highlighted dot.

First, you take it’s value in Celcius, and multiply it by 1.3820366 (which is 28.47)

Then,you add 39.2752753 to it (which is 67.74)

Then, you add the residual error to give us the observed data point.

The generic formula for finding the value for any data point is
\[
F_i = 39.3 + (1.4\times C_i) + \epsilon_i.
\] In this formula the \(i\) is convention for referring to some generic, \(i^{th}\) data point and \(\epsilon\) is conventional for referring to the residual errors.
Some additional conventions:
- Referring to the outcome variable as \(y\).
- Referring to the predictors as \(x\).
- Referring to the remaining parameters as \(\beta\).
So you may sometimes see people referring to \(\beta_0\), or the “betas” in a model. The fully generic formula for linear regression is sometimes given as
\[
y_i = \beta_0 + \beta x_i + \epsilon_i
\]
Idiom
- We call the Intercept and Slopes the parameters or coefficients of the model.
- For every data point, the value you get by only using the slopes and intercepts are called the fitted values, and they all lie along the lines you draw.
- Almost every data point’s actual value is different from its fitted value, and these differences are called the residuals.
Understanding categorical predictors
Categorical variables are necessarilly treated differently in regression models. This is because while you can multiply numeric predictors together, you can’t multiply 5 \(\times\) “experimental condition”.
To illustrate how categorical predictors work in a linear regression, we’ll use some example weather data. I pulled this data of the daily temperature from the University of Edinburgh Geosciences Department weather station.

In order to focus on a categorical effect, I’ve recoded the date variable into “seasons” like so:
| Jan |
Winter |
| Feb |
Winter |
| Mar |
Spring |
| Apr |
Spring |
| May |
Spring |
| Jun |
Summer |
| Jul |
Summer |
| Aug |
Summer |
| Sep |
Autumn |
| Oct |
Autumn |
| Nov |
Autumn |
| Dec |
Winter |
We’ll focus on just the subset of 2010 and 2011, because 2010 was a notably cold winter. Here’s all of the data for the four seasons from 2010 and 2011.

Winter is the “reference level”, for the season’s factor, which you can see if you use levels().
levels(temps_comp$season)
[1] "Winter" "Spring" "Summer" "Autumn"
When using treatment contrasts, the first level is always treated as the reference level.
If we fit a linear model to this data, we get the following solution:
Call:
lm(formula = temp ~ season, data = temps_comp)
Residuals:
Min 1Q Median 3Q Max
-11.5316 -1.7289 0.1078 1.8931 11.2572
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.7283 0.2312 11.80 <2e-16 ***
seasonSpring 5.2934 0.3338 15.86 <2e-16 ***
seasonSummer 10.7282 0.3265 32.86 <2e-16 ***
seasonAutumn 6.9975 0.3293 21.25 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.102 on 698 degrees of freedom
Multiple R-squared: 0.6154, Adjusted R-squared: 0.6137
F-statistic: 372.2 on 3 and 698 DF, p-value: < 2.2e-16
We’ve got a bunch of parameter estimates under “Estimate” and a bunch of significant p-values. But what does it mean to say “There is a significant effect of Spring”? And can we say anthing about, say, the difference between Spring and Autumn? Approach results that look like this exactly like you would a regression with continuous predictors: try to draw the graph it is a recipe for.
We start with the “Intercept”. With continuous predictors, the “intercept” is the y value where the line crosses 0 on the x-axis (a.k.a. the predicted value of the outcome variable when the predictor variable is 0). With categorical variables, there are no lines to draw to describe the relationship between outcome and predictor, so calling it an intercept is more of a metaphorical holdover of the continuous case.
Understand the “Intercept” for categorical predictors to be the predicted average of the reverence level. For the seasons model, the intercept is 2.73, meaning the estimated average winter temperature in Edinburgh is 2.73

Next, we move to the the Spring effect. Model estimates a Spring effect of 5.29. This is not the estimated temperature of Edinburgh in spring. This is how different the Spring temperature is from the Winter temperature. Meaning to get the estimated Spring temperature from the model we need to add the Spring effect to the intercept (2.73 + 5.29 = 8.02)

Next up is the Summer effect, which the model estimates is 10.73. Again, this is not the estimated temperature in the summer. This is how different Summer is estimated to be from the Intercept (Winter). To get the estimated Summer temperature from the model we need to add the Summer effect to the intercept (2.73 + 10.73 = 13.46).

And, what should seem familiar by now, the effect of Autumn is 7, meaning Autumn is 7 degrees warmer than Winter, meaning the estimated average temperature in Autumn is (2.73 + 7 = 9.73).

Let’s review the summary of the model again:
summary(season_model)
Call:
lm(formula = temp ~ season, data = temps_comp)
Residuals:
Min 1Q Median 3Q Max
-11.5316 -1.7289 0.1078 1.8931 11.2572
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.7283 0.2312 11.80 <2e-16 ***
seasonSpring 5.2934 0.3338 15.86 <2e-16 ***
seasonSummer 10.7282 0.3265 32.86 <2e-16 ***
seasonAutumn 6.9975 0.3293 21.25 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.102 on 698 degrees of freedom
Multiple R-squared: 0.6154, Adjusted R-squared: 0.6137
F-statistic: 372.2 on 3 and 698 DF, p-value: < 2.2e-16
We can say the following things about this model:
- The significant
(Intercept) effect means the average temperature in Winter is significantly different from 0 (estimated to be 2.7).
- The significant
seasonSpring effect means the difference between Spring and Winter is significantly different from 0 (Spring is estimated to be 5.3 degreees warmer than Winter.)
- The significant
seasonSummer effect means the difference between Summer and Winter is significantly different from 0 (Summer is estimated to be 10.7 degreees warmer than Winter.)
- The significant
seasonAutumn effect means the difference between Autumn and Winter is significantly different from 0 (Autumn is estimated to be 7 degreees warmer than Winter.)
And that is pretty much all we can say. Looking at these results, we can say that Spring is significantly warmer than Winter, but we can’t say anything about a generic “effect of Spring.” In fact, what would we mean by such a thing anyway?
We also can’t say anything about the difference between any of the other seasons. For example, Spring and Autumn have very similar looking temperatures (their difference from Winter is very similar). We can’t say anything about whether or not Spring is warmer or cooler than Autumn.
A more practical example - Scaling and transorming predictors
We’re now going to walk through a real example from my own research invovling the vowel /ay/. In this example, we’re going to be walking through
Brief Background on /ay/
The English vowel /ay/ is the vowel sound that appears in the English words ride and price. It is a “diphthong”, meaning it is a sound with two different articulatory targets. In the dialect this data is drawn from, the first target is something like a low and back [ɑ], which appears in the words hot and lot, and the second target is something like a high and front [i:], which shows up in the words fleece and heat. We’ll be focusing on just the first part of the diphthong, the typically low and back part.
Vowel sounds can be characterized using both articulatory and acoustic measures, and it has been found that certain acoustic features can be reliably correlated with the articulatory position of the tongue while the vowels are produced. This means we can characterize speakers’ pronunciations of vowel sounds from just a recording of their speech. If we examine how these acoustic properties of vowels covary with speakers’ ages or dates of birth, we can also estimate how pronunciations of these vowels have changed over time.
These acoustic properties are called “formants”, and the formant we are going focus on here is “F1”, which covaries with the height of the tongue in the mouth. The higher F1, the lower in the the mouth the tongue is. It’s also the case that F1 values systematically covary with the length of speakers’ vocal tracts, so we are actually going to be looking at normalized F1, which attempts to factor out this effect.
For this illustration, we’re going to first focus on the vowel /ay/ before voiceless consonants (i.e. /p, t, k, f, s/). In Philadelphia, where this data is from, /ay/ underwent a fairly large shift in its pronunciation across the 20th century.
ayT_means <- ay %>%
filter(plt_vclass == "ay0" )%>% # get the pre-voiceless tokens
mutate(dob = year - age) %>% # calculate speakers' dob
group_by(idstring, dob) %>% # prepare to estimate by-speaker means
summarise(F1_n = mean(F1_n)) # means
ayT_means %>%
ggplot(aes(dob, F1_n))+
geom_point()+
theme_bw()

In this plot, each point represents one speaker. Each speaker’s average normalized F1 value is plotted against their date of birth (ranging from 1889 to 1998). Fitting a linear model to this data appears easy, but actually poses us with interpretive challenges.
ayT_model1 <- lm(F1_n ~ dob, data = ayT_means)
summary(ayT_model1)
Call:
lm(formula = F1_n ~ dob, data = ayT_means)
Residuals:
Min 1Q Median 3Q Max
-0.93874 -0.12952 -0.00738 0.12320 0.82237
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 25.8100970 1.0232146 25.23 <2e-16 ***
dob -0.0129710 0.0005262 -24.65 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2176 on 324 degrees of freedom
Multiple R-squared: 0.6522, Adjusted R-squared: 0.6512
F-statistic: 607.7 on 1 and 324 DF, p-value: < 2.2e-16
Let’s sort out what is being reported here in this model, starting with the intercept.
Estimate Std. Error t value Pr(>|t|)
(Intercept) 25.8100970 1.0232146 25.23 <2e-16 ***
We see here that the intercept is significantly different from 0, but what does this intercept mean? The intercept is the estimated value of the outcome variable when the predictor is 0, meaning the model is predicting a value of normalized F1 of about 26 for speakers born in the year 0.

This is obviously problematic. First, this is a “significant” effect, but it extrapolates so far beyond the data that it’s entirely meaningless. (Nobody was speaking “English” in the year 0.) Second, this estimated normalized F1 value is not a plausible F1 value for any vowel. If you were to try to map this onto an articulatory strategy, speaker’s tongue bodies would be down somewhere around their ankles.
Let’s also look at the slope.
Estimate Std. Error t value Pr(>|t|)
dob -0.0129710 0.0005262 -24.65 <2e-16 ***
This means for every 1 unit increase in dob (i.e. 1 year), there is a decrease of -0.013 in normalized F1.

If we ignore the comically weird intercept, this slope is less problematic. The one major issue in it is its overspecificity. This slope is defined in terms of a change in 1 year of date of birth, but in an important sense that’s over precise. We wouldn’t really want to make any strong inferences about the difference between speakers’ born in 1969 and 1970, for example.
Rescaling
We can address these problems with the modekl by rescaling the date of birth predictor. Rescaling predictors is not only “allowed,” it can be crucial when it comes to trying to fit mixed effects models!
Idiom
Not to confuse things too much, but transormations you make to predictors can be lumped into two broad categories: linear and non-linear. This use of “linear” isn’t related to linear regression in any way. Instead, it describes the relationship between the original measure and the transformed measure.
- addition, subtraction, multiplication, division
Proof by simulation:
linear_df <- data_frame(original = rnorm(100, mean = 50),
addition = original + 10,
subtraction = original - 10,
multiplication = original * 10,
division = original/10)
Any combination of (only) linear transforms is a linear transform.
- logarithms (any base), cosine, square root, etc.
Proof by simulation:
nonlinear_df <- data_frame(original = rnorm(100, mean = 5),
log_ten = log10(original),
cosine = cos(original),
square_root = sqrt(original),
exponential = exp(original))
If we apply one, or many, linear transformations to the predictor variable, we won’t affect the goodness of fit of the model, nor the significance or sign of that predictor. But it will change the way we interpret the effects.
There are a few different kinds of transformations we can do. A very common kind of transformation is to z-score the data. To z-score numeric data, you subtract the mean and divide by the standard deviation. Here’s how that looks in mathematical notation
\[
z = \frac{x-\mu}{\sigma}
\]
Where \(\mu\) is the mean of the \(x\) data, and \(\sigma\) is the standard deviation. Here’s how that looks in practice. The date of birth of speakers has the following distribution of data, with the meand and \(\pm1\) standard deviation annotated.

By subtracting out the mean, we center this distribution on 0, and by dividing by the standard deviation, we shrink down the distribution so that 1 standard deviation from the mean is the value 1. Here’s how the result looks:

Why is this an improvement?
Let’s re-fit the model with this transformed DOB predictor and see:
ayT_model2 <- lm(F1_n ~ dob_z, data = ayT_means)
summary(ayT_model2)
Call:
lm(formula = F1_n ~ dob_z, data = ayT_means)
Residuals:
Min 1Q Median 3Q Max
-0.93874 -0.12952 -0.00738 0.12320 0.82237
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.58862 0.01205 48.83 <2e-16 ***
dob_z -0.29760 0.01207 -24.65 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2176 on 324 degrees of freedom
Multiple R-squared: 0.6522, Adjusted R-squared: 0.6512
F-statistic: 607.7 on 1 and 324 DF, p-value: < 2.2e-16
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.58862 0.01205 48.83 <2e-16 ***
The intercept is the estimated value of normalized F1 when dob_z is 0, which is the mean of dob, 1944.

Estimate Std. Error t value Pr(>|t|)
dob_z -0.29760 0.01207 -24.65 <2e-16 ***
The slope tells us how much normalized F1 changes for every change of 1 standard deviation of dob (23 years)
For every 1 standard deviation shift in dob (23 years), there is a decrease of 0.3 in normalized F1.

These values of the intercept and slope are more interpretable.
Are we really allowed to do all this rescaling?
Yes, but, you must explain what you did in the write up. For example:
The date of birth predictor was centered on 1960, and divided by 10. The 1960 was chosen as the centering point because of its importance in previous sociolinguistic studies. Dividing dob by 10 gives the resulting slope the interpretation of the rate of change per decade.
Multivariate Models & Interactions
We’re quickly going to go over multivariate models (multiple predictors) and interactions. The important thing to keep in mind when including multiple predictor is that your reference level and scaling of each predictor is going to start to matter a lot more.
Continious and categorical predictors
Let’s start with the /ay/ data. Previously we were looking only at pre-voiceless /ay/. But now we’re going to look at all /ay/, with each token coded for whether it’s pre-voiceless, or elsewhere. This is encoded in the plt_vclass column.
plt_vclass
ay0 - Pre-voiceless /ay/
ay - All other /ay/.
Because we’re not dealing with mixed effects models yet, we’ll first calculate by-speaker means. In the process I’ll be re-scaling date of birth with two differing centering points, one on 1900, and one on 1960.
ay_means <- ay %>%
mutate(dob = year-age) %>%
group_by(idstring, dob, plt_vclass) %>%
summarise(F1_n = mean(F1_n))%>%
mutate(decade_1900 = (dob - 1900)/10,
decade_1960 = (dob - 1960)/10,
voicing = factor(recode(plt_vclass, ay0 = "voiceless",
ay = "else")),
voicing = relevel(voicing, "else"))
ggplot(ay_means, aes(dob, F1_n, color = voicing))+
geom_point()+
theme_bw()

Two predictors, no interactions
We can see that there is a big difference between pre-voiceless and elsewhere /ay/. Let’s start building up the model then
ay_model1 <- lm(F1_n ~ decade_1900 + voicing, data = ay_means)
summary(ay_model1)
Call:
lm(formula = F1_n ~ decade_1900 + voicing, data = ay_means)
Residuals:
Min 1Q Median 3Q Max
-1.01218 -0.14438 -0.01086 0.13725 0.77522
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.567577 0.020862 75.14 <2e-16 ***
decade_1900 -0.075493 0.003793 -19.91 <2e-16 ***
voicingvoiceless -0.643357 0.017376 -37.02 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2218 on 649 degrees of freedom
Multiple R-squared: 0.7314, Adjusted R-squared: 0.7305
F-statistic: 883.5 on 2 and 649 DF, p-value: < 2.2e-16
Let’s walk through the effects by drawing the graph that this model is a recipe for. First, we have the Intercept.
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.567577 0.020862 75.14 <2e-16 ***
This is the estimated average value of normalized F1 for when all predictors are 0. That means this is the predicted intercept when the centered dob is 0 (1900), for the reference level (elsewhere /ay/)

Next there’s the slope:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.567577 0.020862 75.14 <2e-16 ***
There’s a few different ways we could construe this slope. The value is the rate of change per decade, and we’ll interpret this as the slope for reference level.

Finally, there’s the voicing parameter.
Estimate Std. Error t value Pr(>|t|)
voicingvoiceless -0.643357 0.017376 -37.02 <2e-16 ***
This tells us how different the intercept of the line for pre-voiceless /ay/ is from elsewhere /ay/. Because we have included no other effects or interactions, the model is assuming that the slope of the pre-voiceless /ay/ is identical to elsewhere /ay/.

Note, looking a this graph, you can see that this voiceless effect is not the estimated intercept of pre-voicelss /ay/. It is the estimated difference in intercepts between these two lines.
Evaluating the model.
Let’s look at the model summary again:
summary(ay_model1)
Call:
lm(formula = F1_n ~ decade_1900 + voicing, data = ay_means)
Residuals:
Min 1Q Median 3Q Max
-1.01218 -0.14438 -0.01086 0.13725 0.77522
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.567577 0.020862 75.14 <2e-16 ***
decade_1900 -0.075493 0.003793 -19.91 <2e-16 ***
voicingvoiceless -0.643357 0.017376 -37.02 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2218 on 649 degrees of freedom
Multiple R-squared: 0.7314, Adjusted R-squared: 0.7305
F-statistic: 883.5 on 2 and 649 DF, p-value: < 2.2e-16
If you only fit this model, and didn’t plot any of the data, you might conclude:
- There is a significant change over decade for /ay/.
- There is a significant effect of voicing on /ay/.
Including interactions
However, looking at the plot, it’s clear something more complicated is going on. Neither of the lines look like they’re passing through their related data points very well. There is, in fact, an interaction between voicing and date of birth. Pre-voiceless /ay/ is undergoing a change, while elsewhere /ay/ is basically staying the same. We can account for this by including this interaction in the model:
ay_model2 <- lm(F1_n ~ decade_1900 * voicing, data = ay_means)
summary(ay_model2)
Call:
lm(formula = F1_n ~ decade_1900 * voicing, data = ay_means)
Residuals:
Min 1Q Median 3Q Max
-0.93874 -0.11050 -0.00824 0.10554 0.82237
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.326564 0.022219 59.703 < 2e-16 ***
decade_1900 -0.021277 0.004443 -4.789 2.08e-06 ***
voicingvoiceless -0.161329 0.031423 -5.134 3.75e-07 ***
decade_1900:voicingvoiceless -0.108433 0.006283 -17.257 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared: 0.816, Adjusted R-squared: 0.8151
F-statistic: 957.6 on 3 and 648 DF, p-value: < 2.2e-16
Let’s build up the graph.
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.326564 0.022219 59.703 < 2e-16 ***
This is the estimated average for when all preditors are 0 (i.e. dob = 1900, voicing = else).

Estimate Std. Error t value Pr(>|t|)
decade_1900 -0.021277 0.004443 -4.789 2.08e-06 ***
This is the estimated slope for the reference level (i.e. voicing = else)

Now, we get into the more complicated coefficients.
Estimate Std. Error t value Pr(>|t|)
voicingvoiceless -0.161329 0.031423 -5.134 3.75e-07 ***
This is how different the line for pre-voiceless /ay/ is from elsewhere /ay/ at the intercept (i.e. when dob = 1900).

Finally, we have the interaction effect.
Estimate Std. Error t value Pr(>|t|)
decade_1900:voicingvoiceless -0.108433 0.006283 -17.257 < 2e-16 ***
This is the most easilly misinterpretable parameter in this model. It is not the estimated slope of pre-voiceless /ay/. It is how different pre-voiceless /ay/’s slope is from elsewhere /ay/. That is, if you drew a line parallel to elsewhere /ay/, thos is how much you’d have to rotate the the line to get pre-voiceless /ay/’s slope.

Be careful thinking about models with interactions
This is super important to keep in mind, let’s say we ran this model, and got the following coefficients:
(Intercept) 1.32 ***
decade_1900 -10 ***
voicingvoiceless -0.16 ***
decade_1900:voicingvoiceless 10 ***
The significant interaction between date of birth and voicing here would not mean that there is significant change for pre-voiceless /ay/ over time. It means there is a significant difference between the slope of elsewhere /ay/ and pre-voiceless /ay/. The estimated slope of elsewhere /ay/ in this fake model is -10, and for pre-voiceless /ay/ it’s -10 + 10 = 0!
The other thing to keep in mind with interpreting the results of the model is that the voicingvoiceless effect is not an estimate of “the effect of voicing.” It is the estimated difference between the two lines at the intercept. If we change where the intercept is, for example by using a different scaling, we also change the value of this parameter.
summary(lm(F1_n ~ decade_1900 * voicing, data = ay_means))
Call:
lm(formula = F1_n ~ decade_1900 * voicing, data = ay_means)
Residuals:
Min 1Q Median 3Q Max
-0.93874 -0.11050 -0.00824 0.10554 0.82237
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.326564 0.022219 59.703 < 2e-16 ***
decade_1900 -0.021277 0.004443 -4.789 2.08e-06 ***
voicingvoiceless -0.161329 0.031423 -5.134 3.75e-07 ***
decade_1900:voicingvoiceless -0.108433 0.006283 -17.257 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared: 0.816, Adjusted R-squared: 0.8151
F-statistic: 957.6 on 3 and 648 DF, p-value: < 2.2e-16
summary(lm(F1_n ~ decade_1960 * voicing, data = ay_means))
Call:
lm(formula = F1_n ~ decade_1960 * voicing, data = ay_means)
Residuals:
Min 1Q Median 3Q Max
-0.93874 -0.11050 -0.00824 0.10554 0.82237
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.198902 0.012301 97.467 < 2e-16 ***
decade_1960 -0.021277 0.004443 -4.789 2.08e-06 ***
voicingvoiceless -0.811927 0.017396 -46.674 < 2e-16 ***
decade_1960:voicingvoiceless -0.108433 0.006283 -17.257 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared: 0.816, Adjusted R-squared: 0.8151
F-statistic: 957.6 on 3 and 648 DF, p-value: < 2.2e-16
With the date of birth centered on 1900, we get a relatively weak effect (-0.16). With the date of birth centered on 1960, we get a much stronger effect (-0.81). That’s because there is a strong interaction between the date of birth and voicing context, and there is a bigger difference between these two lines in 1960 than in 1900!

It is, in fact, more than possible for a predictor like this to have an estimated value close to 0, and be non-significant, but for it to actuallty matter a lot to the model.
Lessons
- Always think carefully about the meaning of predictors in a model with interactions.
- Always try to draw the graph out.
- Always remember the parameters are estimates of the difference from the reference levels.
- Non-significant != not important.
Categorical interactions.
We’ll return to the weather data to examine the interpretation of categorical interactions. We’ll be using season and a categorical coding of year.
temps_comp <- temps_comp %>%
mutate(year_factor = factor(year))
Fitting the model is straight forward.
temps_model <- lm(temp ~ season * year_factor, data = temps_comp)
summary(temps_model)
Call:
lm(formula = temp ~ season * year_factor, data = temps_comp)
Residuals:
Min 1Q Median 3Q Max
-10.336 -1.744 0.041 1.726 11.898
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.2151 0.3092 3.929 9.37e-05 ***
seasonSpring 6.1661 0.4603 13.395 < 2e-16 ***
seasonSummer 12.7472 0.4385 29.067 < 2e-16 ***
seasonAutumn 7.3150 0.4451 16.436 < 2e-16 ***
year_factor2011 3.0264 0.4373 6.920 1.03e-11 ***
seasonSpring:year_factor2011 -1.8707 0.6333 -2.954 0.00324 **
seasonSummer:year_factor2011 -4.0215 0.6176 -6.511 1.43e-10 ***
seasonAutumn:year_factor2011 -0.7270 0.6231 -1.167 0.24375
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.934 on 694 degrees of freedom
Multiple R-squared: 0.6579, Adjusted R-squared: 0.6545
F-statistic: 190.7 on 7 and 694 DF, p-value: < 2.2e-16
There’s a lot going on here, and it is very easy to misinterpret the results if you don’t try to draw out the graph. We’ll take the coefficients in batches. First, there is the “intercept.”
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.2151 0.3092 3.929 9.37e-05 ***
This is the estimated average temperature for the references levels, that is, for season = Winter, year = 2010.

Next, there are the season effects.
Estimate Std. Error t value Pr(>|t|)
seasonSpring 6.1661 0.4603 13.395 < 2e-16 ***
seasonSummer 12.7472 0.4385 29.067 < 2e-16 ***
seasonAutumn 7.3150 0.4451 16.436 < 2e-16 ***
Recall, these are the estimated differences between Winter and the named season. But because there is an interaction effect between season and year, these values are even more specific: these are the estimated differences between each of these named seasons and Winter in 2010, because 2010 is the reference level for year.

Next is the year effect
Estimate Std. Error t value Pr(>|t|)
year_factor2011 3.0264 0.4373 6.920 1.03e-11 ***
Again, because there is an interaction effect between season and year, this is estimated difference between Winter 2010 and Winter 2011. I’m drawing this on the graph for winter in a solid line, and for all of the other seasons in a dashed line. As will be made clear in a moment, this is is because the interaction effects can only be interpreted in relation to these dashed lines.

Finally, there are the interation terms!
Estimate Std. Error t value Pr(>|t|)
seasonSpring:year_factor2011 -1.8707 0.6333 -2.954 0.00324 **
seasonSummer:year_factor2011 -4.0215 0.6176 -6.511 1.43e-10 ***
seasonAutumn:year_factor2011 -0.7270 0.6231 -1.167 0.24375
The effect of year in the model was about 3, meaning Winter 2011 was 3 degrees warmer than Winter 2010. If we look at the Spring:Year interaction here, it has a value of -1.9, meaning Spring 2011 was 3-1.9 = 1.1 degree warmer than Spring 2010.
That is, these interaction terms are telling us how different the year effect for each season is from the year effect for Winter, our reference level. Just because Spring:2011 has a significant negative value doesn’t mean Spring 2011 was colder than Spring 2010! It just means that the difference between Spring 2010 and Spring 2011 was not as big as that between Winter 2010 and Winter 2011!
The significant Spring:2011 effect also does not mean that Spring 2011 was a significantly different temperature than Spring 2010!

Next Week
- Introducing Mixed Effects Models
LS0tCnRpdGxlOiAiSW50cm8gJiBSZXZpZXdpbmcgTGluZWFyIE1vZGVscyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogbm9uZQogICAgY3NzOiAuLi9jdXN0b20uY3NzCiAgICB0aGVtZTogZmxhdGx5CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19kZXB0aDogMwotLS0KCiMgQWdlbmRhCgoxLiBJbnRyb2R1Y3Rpb25zCjIuIENvdXJzZSBBZG1pbgozLiBTZXR1cAo0LiBSZXZpZXdpbmcgdGhlIG1vc3QgaW1wb3J0YW50IHBhcnRzIG9mIExpbmVhciBNb2RlbHMKCgojIEludHJvZHVjdGlvbnMKCjxkaXYgY2xhc3MgPSAiYm94IGJyZWFrIj4KPHNwYW4gY2xhc3MgPSAiYmlnLWxhYmVsIj5IZWxsbyE8L3NwYW4+CgpNeSBuYW1lIGlzIEpvc2VmIEZydWVod2FsZCwgYW5kIEknbSBhIGxlY3R1cmVyIGluIExpbmd1aXN0aWNzIGFuZCBFbmdsaXNoIExhbmd1YWdlLgoKPC9kaXY+CgpJbiB0aGlzIGZpcnN0IGJsb2NrIG9mIG11bHRpdmFyaWF0ZSBzdGF0cywgd2UnbGwgYmUgY292ZXJpbmcKCi0gVGhlIHJlYXNvbnMgd2h5IHlvdSBzaG91bGQgZml0IExpbmVhciBNaXhlZCBFZmZlY3RzIG1vZGVscy4KLSBIb3cgdG8gZml0IExNTXMuCi0gSG93IHRvIGludGVycHJldCB0aGUgcmVzdWx0cyBvZiBMTU1zLgotIEhvdyB0byBkbyBtb2RlbCBjb21wYXJpc29uICYgcGFyYW1ldGVyIGV2YWx1YXRpb24uCi0gSG93IHRvIHJlcG9ydCB0aGUgcmVzdWx0cyBvZiB5b3VyIExNTXMuCi0gU29tZSBwcmFnbWF0aWMgaXNzdWVzIGluIHRoaW5raW5nIGFib3V0IHlvdXIgcmVzdWx0cy4KCkluIHRoZSBsYWIgc2Vzc2lvbnMsIHlvdSdsbCB3b3JrIHRocm91Z2ggZXhlcmNpc2VzIHJlbGF0ZWQgdG8gZml0dGluZyBMTU1zLCBhcyB3ZWxsIGFzIHJlbGF0ZWQgUiBwcm9ncmFtbWluZyBza2lsbHMgcmVsYXRlZCB0byBkYXRhIG9yZ2FuaXphdGlvbiBhbmQgdmlzdWFsaXphdGlvbi4KCiMgQ291cnNlIEFkbWluCgpBbGwgbGVjdHVyZXMgd2lsbCBpbmNsdWRlIHNvbWUgUiBwcm9ncmFtbWluZyB5b3UgY2FuIGRvIGR1cmluZyB0aGUgbGVjdHVyZS4gSSdsbCByZWNvbW1lbmQgdGhhdCB5b3UgY3JlYXRlIGEgZnJlc2ggUiBOb3RlYm9vayBmb3IgZWFjaCBsZWN0dXJlLgoKPGRpdiBjbGFzcyA9ICJib3ggYnJlYWsiPgo8c3BhbiBjbGFzcyA9ICJiaWctbGFiZWwiPn41IE1pbnV0ZSBTZXR1cDwvc3Bhbj4KCkZpcnN0IGNyZWF0ZSBhIG5ldyBSIE5vdGVib29rIGZvciB0aGlzIGxlY3R1cmUgd2l0aCBgRmlsZSA+IE5ldyBGaWxlID4gUiBOb3RlYm9va2AuIEkgd291bGQgcmVjb21tZW5kIGNoYW5naW5nIHRoZSB0b3AgaGVhZGVyIG1ldGFkYXRhIHNvIGl0IGhhcyBhIG1lYW5pbmdmdWwgdGl0bGU6CgpgYGAKLS0tCnRpdGxlOiAiTXVsdGl2YXJpYXRlIC0gTGVjdHVyZSAxIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYAoKRGVsZXRlIGV2ZXJ5dGhpbmcgZWxzZSBpbiB0aGUgbm90ZWJvb2suCgo8aHI+CgpOb3csIGxldCdzIGluc3RhbGwgc29tZSBwYWNrYWdlcyB0aGF0IHdpbGwgYmUgbmVjZXNzYXJ5IGluIHRoZXNlIGxlY3R1cmVzOgoKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKAogIGMoInRpZHl2ZXJzZSIsCiAgICAiZGV2dG9vbHMiLAogICAgImxtZTQiKQopCgpsaWJyYXJ5KCJkZXZ0b29scyIpCgppbnN0YWxsX2dpdGh1Yigiam9mcmh3bGQvbXVsdGl2YXJpYXRlMjAxNyIpCgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsbWU0KQpsaWJyYXJ5KG11bHRpdmFyaWF0ZTIwMTcpCmBgYAoKCgo8L2Rpdj4KCgo8ZGl2IGNsYXNzID0gImJveCBoeWdpZW5lIj4KPHNwYW4gY2xhc3MgPSAibGFiZWwiPldvcmtzcGFjZSBIeWdpZW5lPC9zcGFuPgoKIyMgUmVjb21tZW5kZWQgQ291cnNlIERpcmVjdG9yeSBTdHJ1Y3R1cmUKCklmIHlvdSBoYXZlIGEgZGlyZWN0b3J5IHBsYW5uaW5nIHN0cnVjdHVyZSB0aGF0IHlvdSdyZSBoYXBweSB3aXRoLCBnbyBhaGVhZCBhbmQgZG8gdGhhdC4gQnV0IEknZCByZWNvbW1lbmQgdGhlIGZvbGxvd2luZyBkaXJlY3Rvcnkgc3RydWN0dXJlICYgbmFtaW5nIGNvbnZlbnRpb25zLgoKICAgIOKUnOKUgOKUgCBtdWx0aXZhcmlhdGVfMjAxNwogICAg4pSCwqDCoCDilJTilIDilIAgbG1tCiAgICDilILCoMKgIOKUgsKgwqAg4pSU4pSA4pSAIGFzc2Vzc21lbnQKICAgIOKUgsKgwqAg4pSCwqDCoCDilJTilIDilIAgZGF0YQogICAg4pSCwqDCoCDilILCoMKgIOKUlOKUgOKUgCBsYWJzCgpGb3IgYSBnb29kIHBoaWxvc29waHkgb24gbmFtaW5nIGZpbGVzLCBJJ2QgcmVjb21tZW5kIFt0aGVzZSBzbGlkZXMgZnJvbSBKZW5ueSBCcnlhbidzIHRhbGsgb24gTmFtaW5nIFRoaW5nc10oaHR0cDovL3d3dzIuc3RhdC5kdWtlLmVkdS9+cmNzNDYvbGVjdHVyZXNfMjAxNS8wMS1tYXJrZG93bi1naXQvc2xpZGVzL25hbWluZy1zbGlkZXMvbmFtaW5nLXNsaWRlcy5wZGYpCgpBbHNvIGdvb2QgcHJhY3RpY2UgaXMgdG8gbG9hZCBhbGwgdGhlIHBhY2thZ2VzIHlvdSdyZSBnb2luZyB0byBuZWVkIGF0IHRoZSAqdG9wKiBvZiB5b3VyIHNjcmlwdC9ub3RlYm9vayBpbiBvbmUgYmxvY2ssIHJhdGhlciB0aGFuIGhhcGhhemFyZGx5IHRocm91Z2hvdXQuCgo8L2Rpdj4KCgojIFRoZSBQbGFuIEZvciBUaGlzIFdlZWsKCiMjIExlY3R1cmUKClRvZGF5LCB3ZSdyZSBnb2luZyB0byBnb2luZyB0byByZXZpZXcgdGhlIGVzdGltYXRpb24gJiBpbnRlcnByZXRhdGlvbiBvZiBsaW5lYXIgbW9kZWxzLCB3aXRoIGEgZm9jdXMgb246CgotIHRoZSBzY2FsaW5nICYgdHJhbnNmb3JtYXRpb24gb2YgcHJlZGljdG9ycwotIHRoZSBzZWxlY3Rpb24gb2YgY29udHJhc3RzCi0gdGhlIGludGVycHJlYXRpb24gb2YgaW50ZXJhY3Rpb24gZWZmZWN0cwoKIyMgTGFicwoKVGhlIGxhYiBleGVyY2lzZXMgdGhpcyB3ZWVrIHdpbGwgZm9jdXMgb24gZGF0YSAocmUpb3JnYW5pemF0aW9uIGFuZCB2aXp1YWxpemF0aW9uLgoKCiMgVW5kZXJzdGFuZGluZyBMaW5lYXIgUmVncmVzc2lvbgoKCgpJIGZpbmQgdGhlIGJlc3Qgd2F5IHRvIHVuZGVyc3RhbmQgbGluZWFyIHJlZ3Jlc3Npb25zIGlzIGFzIHJlY2lwZXMgZm9yIGRyYXdpbmcgYSBncmFwaC4gTGV0J3Mgc3RhcnQgb2ZmIHdpdGggYW4gZXhhbXBsZSByZWxldmFudCB0byBteSBvd24gbGlmZTogdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRlbXBlcmF0dXJlcyBpbiBDZWxjaXVzIGFuZCB0ZW1wZXJhdHVyZXMgaW4gRmFyZW5oZWl0LiBUaGVyZSBhcmUgdHdvIGltcG9ydGFudCBudW1lcmljIGNvbnN0YW50cyB0byBjb252ZXJ0IGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gdGhlbToKCjEuIEZyZWV6aW5nID0gMCYjMTc2O0MgPSAzMiYjMTc2O0YKMi4gQSBjaGFuZ2Ugb2YgMSYjMTc2O0MgPSAxLjgmIzE3NjtGCgoKVGhpcyBnaXZlcyB1cyBhbGwgb2YgdGhlIG5lY2Vzc2FyeSBjb21wb25lbnRzIGZvciBkcmF3aW5nIGEgZ3JhcGggb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEZhcmVuaGVpdCBhbmQgQ2VsY2l1cy4gRmlyc3QsIHdlIGtub3cgdGhhdCBhIGxpbmUgcGxvdHRpbmcgdGhpcyByZWxhdGlvbnNoaXAgbXVzdCBjcm9zcyAwIG9uIHRoZSB4LWF4aXMgYXQgMzIgb24gdGhlIHktYXhpcywgYmVjYXVzZSBmcmVlemluZyA9IDAmIzE3NjtDID0gMzImIzE3NjtGLgoKCmBgYHtyIGVjaG8gPSBGfQpsaWJyYXJ5KGdyaWQpCmdncGxvdCgpKwogIHhsaW0oLTMsIDQwKSsKICB5bGltKDAsIDQwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgYW5ub3RhdGUoZ2VvbSA9ICJwb2ludCIsIHggPSAwLCB5ID0gMzIsIGNvbG9yID0gJ3JlZCcpKwogIHhsYWIoIkNlbGNpdXMiKSsKICB5bGFiKCJGYXJlbmhlaXQiKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgY29vcmRfZml4ZWQoKQpgYGAKCk5leHQsIHdlIGtub3cgdGhhdCBmb3IgMSBldmVyeSBkZWdyZWUgd2UgbW92ZSB0byB0aGUgcmlnaHQsIHdlIG11c3QgbW92ZSB1cCAxLjguCgpgYGB7ciBlY2hvID0gRn0KCmZjIDwtIGRhdGFfZnJhbWUoY2VsY2l1cyA9IGMoMCwgMSwgMiwgMywgNCksCiAgICAgICAgICAgICAgICAgRmFyZW5oZWl0ID0gKGNlbGNpdXMgKiAxLjgpICsgMzIpCgpnZ3Bsb3QoZmMpKwogIHhsaW0oLTMsIDQwKSsKICB5bGltKDAsIDQwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgZ2VvbV9zdGVwKGFlcyh4ICA9IGNlbGNpdXMsIHkgPSBGYXJlbmhlaXQpKSsgIAogIGdlb21fcG9pbnQoYWVzKHggID0gY2VsY2l1cywgeSA9IEZhcmVuaGVpdCksIAogICAgICAgICAgICAgY29sb3IgPSAncmVkJykrCiAgeGxhYigiQ2VsY2l1cyIpKwogIHlsYWIoIkZhcmVuaGVpdCIpKwogIHRoZW1lX21pbmltYWwoKSsKICBjb29yZF9maXhlZCgpCmBgYAoKVGhlIGxpbmUsIHJlcHJlc2VudGluZyB0aGlzIHJlbGF0aW9uc2hpcCwgdGh1cyBoYXMgdGhlIGZvcm11bGE6CgokJAp5ID0gMzIgKyAoMS44XHRpbWVzIHgpCiQkCgpBbmQgbG9va3MgbGlrZQoKYGBge3IgZWNobyA9IEZ9CgpnZ3Bsb3QoZmMpKwogIHhsaW0oLTMsIDYwKSsKICB5bGltKDAsIDYwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgZ2VvbV9zdGVwKGFlcyh4ICA9IGNlbGNpdXMsIHkgPSBGYXJlbmhlaXQpKSsgIAogIGdlb21fcG9pbnQoYWVzKHggID0gY2VsY2l1cywgeSA9IEZhcmVuaGVpdCksIAogICAgICAgICAgICAgY29sb3IgPSAncmVkJykrCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMzIsIHNsb3BlID0gMS44LCBjb2xvciA9ICdyZWQnKSsKICB4bGFiKCJDZWxjaXVzIikrCiAgeWxhYigiRmFyZW5oZWl0IikrCiAgdGhlbWVfbWluaW1hbCgpKwogIGNvb3JkX2ZpeGVkKCkKYGBgCgpUaGlzIGxpbmUgaGFzIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczoKCjEuIEl0cyAqKkludGVyY2VwdCoqLCBvciB3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcywgaXMgMzIuCjIuIEl0cyAqKlNsb3BlKiosIGlzIDEuOCAodGhhdCBpcywgYSBjaGFuZ2Ugb2YgMSBvbiB0aGUgeC1heGlzIGNvcnJlc3BvbmRzIHRvIGEgY2hhbmdlIGluIDEuOCBvbiB0aGUgeS1heGlzKQoKCkFuZCwgaW4gZmFjdCwgKmFsbCogbGluZXMsIGluY2x1ZGluZyB0aGUgb25lcyB3ZSBmaXQgdXNpbmcgbGluZWFyIHJlZ3Jlc3Npb24sIGFyZSBkZXNjcmliZWQgaW4gdGVybXMgb2YgdGhlaXIgaW50ZXJjZXB0ICh3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcykgYW5kIHNsb3BlLgoKCkJ1dCwgbGV0J3Mgc2F5IHlvdSBkaWRuJ3Qga25vdyB0aGUgZm9ybXVsYSB0byBjb252ZXJ0IGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gQ2VsY2l1cyBhbmQgRmFyZW5oZWl0LiBNYXliZSB5b3Ugd2VyZW4ndCBldmVuIHN1cmUgdGhhdCB0aGVyZSB3YXMgc3VjaCBhIGZvcm11bGEuIEFuZCBhbGwgeW91IGhhZCB3ZXJlIGEgYnVuY2ggb2Yga2luZCBvZiBjcmFwcHkgdGhlcm1vbWV0ZXJzIHRoYXQgZ2F2ZSB5b3UgYm90aCBDZWxjaXVzIGFuZCBGYXJlbmhlaXQgcmVhZGluZ3MuIEFuZCBtYXliZSB0aGUgdGhlcm1vbWV0ZXJzIGFyZSBraW5kIG9mIGhhcmQgdG8gcmVhZCwgb3IgdGhlIGxpZ2h0aW5nIGNvbmRpdGlvbnMgYXJlIGRhcmssIG9yIHlvdSBvbmx5IGhhdmUgbGltaXRlZCBleHBlcmllbmNlIGluIHJlYWRpbmcgdGhlcm1vbWV0ZXJzLiBJbiB0aGF0IGNhc2UsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBDZWxjaXVzIGFuZCBGYXJlbmhlaXQgbWlnaHQgbG9vayBhIGxvdCBtb3JlIGxpa2UgdGhpczoKCmBgYHtyLCBlY2hvID0gRn0KdHJ1ZV9jIDwtIGMoMCwgMTAsIDE2LCAyMCwgMjMsIDMwKQp0cnVlX2YgPC0gKHRydWVfYyoxLjgpICsgMzIKY19vYnNlcnZlIDwtIG1hcCh0cnVlX2MsIH5ybm9ybSgyMCwgbWVhbiA9IC54LCBzZCA9IDUpKSAlPiUgc2ltcGxpZnkoKQpmX29ic2VydmUgPC0gbWFwKHRydWVfZiwgfnJub3JtKDIwLCBtZWFuID0gLngsIHNkID0gNSoxLjgpKSAlPiUgc2ltcGxpZnkoKQoKdGVtcF9kZiA8LSBkYXRhLmZyYW1lKGNfb2JzZXJ2ZSA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgIGZfb2JzZXJ2ZSA9IGZfb2JzZXJ2ZSkKCgp0ZW1wX2RmICU+JQogIGdncGxvdChhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrICAKICAgICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSAzMiwgc2xvcGUgPSAxLjgsIGNvbG9yID0gImdyZXk0MCIpKwogICAgZ2VvbV9wb2ludCgpKwogICAgI3N0YXRfc21vb3RoKG1ldGhvZCA9IGxtKSsKICAgICN4bGltKC0xMCwgNDApKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgI3lsaW0oMCwgMTAwKSsKICAgIHlsYWIoIkZhcmVuaGVpdCIpKwogICAgY29vcmRfZml4ZWQoKSsKICAgIHRoZW1lX21pbmltYWwoKQoKYGBgCgoKSW4gdGhpcyBjYXNlLCB5b3UgbWlnaHQgd2FudCB0byBmaXQgYSAqKmxpbmVhciByZWdyZXNzaW9uKiouIEEgbGluZWFyIHJlZ3Jlc3Npb24gYXNzdW1lcyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28gdmFyaWFibGVzIGNhbiBiZSBjYXB0dXJlZCB1c2luZyAqc29tZSogbGluZSwgYW5kIGl0IHRyaWVzIHRvIGVzdGltYXRlIHRoZSAqSW50ZXJjZXB0KiBhbmQgKlNsb3BlKiBvZiB0aGlzIGFzc3VtZWQgbGluZS4KClRoZSB3YXkgaXQgZG9lcyB0aGlzIGlzIGJ5IHRyeWluZyB0byBmaW5kIHBhcmFtZXRlcnMgZm9yIGEgbGluZSB0aGF0IG1pbmltaXplIHRoZSAiZXJyb3IiIG9yIHRoZSAicmVzaWR1YWxzIiBiZXR3ZWVuIHRoZSBvYnNlcnZlZCBkYXRhLCBhbmQgdGhlIGxpbmUuIEZvciBleGFtcGxlLCBoZXJlIGFyZSBleGFtcGxlcyBvZiAqYmFkKiBsaW5lcy4gVGhlIGZpcnN0IGFzc3VtZXMgdGhhdCBhbGwgdGVtcGVyYXR1cmVzIENlbGNpdXMgYXJlIGJhc2ljYWxseSA1MCYjMTc2O0YuIFRoZSBvdGhlciBhc3N1bWVzIHRoYXQgYWxsIHRlbXBlcmF0dXJlcyBpbiBGYXJlbmhlaXQgYXJlIGJhc2ljYWxseSAzJFx0aW1lcyRDLgoKPGRpdiBzdHlsZSA9ICJmbG9hdDpsZWZ0O3dpZHRoID0gNDUlOyI+CmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBjX29ic2VydmUsIHllbmQgPSA1MCkpKwogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBjb2xvciA9ICdyZWQnKSsKICAgICNzdGF0X3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICdyZWQnLCBzZSA9IEYpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJGID0gNTAiKQoKYGBgCjwvZGl2Pgo8ZGl2IHN0eWxlID0gImZsb2F0OmxlZnQ7d2lkdGggPSA0NSU7Ij4KYGBge3IgZWNobyA9IEYsIHdpZHRoID0gM30KZ2dwbG90KHRlbXBfZGYsIGFlcyhjX29ic2VydmUsIGZfb2JzZXJ2ZSkpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ZW5kID0gY19vYnNlcnZlLCB5ZW5kID0gY19vYnNlcnZlICogMykpKwogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMywgY29sb3IgPSAicmVkIikrCiAgICAjc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAncmVkJywgc2UgPSBGKSsKICAgIHhsYWIoIkNlbGNpdXMiKSsKICAgIHlsYWIoIkZhcmVuaGVpdCIpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiRiA9IDMqQyIpCgpgYGAKPC9kaXY+CgpIZXJlIGlzIGEgcGxvdCBvZiB0aGUgYmVzdC1maXR0aW5nIGxpbmUsIHRoYXQgaGFzIHRoZSBzbWFsbGVzdCBhdmVyYWdlIHJlc2lkdWFscy4KYGBge3IgZWNobyA9IEZ9CnRlbXBfbW9kIDwtIGxtKGZfb2JzZXJ2ZX5jX29ic2VydmUsIGRhdGEgPSB0ZW1wX2RmKQp0ZW1wX2RmJGZpdHRlZCA8LSBmaXR0ZWQodGVtcF9tb2QpCgpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBjX29ic2VydmUsIHllbmQgPSBmaXR0ZWQpKSsKICAgIGdlb21fcG9pbnQoY29sb3IgPSAiZ3JleTQwIikrCiAgICBzdGF0X3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICdyZWQnLCBzZSA9IEYsIGZ1bGxyYW5nZSA9IFQpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrCiAgICB0aGVtZV9taW5pbWFsKCkKCiAgICAKYGBgCgpUaGVyZSBhcmUgYWN0dWFsbHkgbWFueSBkaWZmZXJlbnQgd2F5cyB0byBmaWd1cmUgb3V0IHdoYXQgdGhlIGJlc3QgbGluZSBpcyAocmVtZW1iZXJpbmcgdGhhdCBieSAibGluZSIgd2UgcmVhbGx5IG1lYW4gdGhlIHBhaXJpbmcgb2YgSW50ZXJjZXB0IGFuZCBTbG9wZSkuIApGb3IgZXhhbXBsZSwgb25lIHJlYWxseSBzaW1wbGlzdGljIGFwcHJvYWNoXltBY3R1YWxseSwgdGhpcyAic2ltcGxpc3RpYyBhcHByb2FjaCIgaXMgbW9yZSBsaWtlIHRoZSBzb3BoaXN0aWNhdGVkIGFwcHJvYWNoIHRoZXNlIGRheXMsIGJlY2F1c2UgdGhlcmUgYXJlIGNvbXBsaWNhdGVkIG1hdGhzIGJlaGluZCBtYWtpbmcgZ29vZCBndWVzc2VzIHdoaWNoIGFyZSBnaXZlbiBzZW1hbnRpY2FsbHkgb3BhcXVlIG5hbWVzIGxpa2UgIlNpbXVsYXRlZCBBbm5lYWxpbmciIGFuZCAiSGFtaWx0b25pYW4gTW9udGUgQ2FybG8iLl0gd291bGQgYmUganVzdCB0byBkcmF3IGEgYnVuY2ggb2YgZGlmZmVyZW50IGxpbmVzLCBhbmQgc2VlIHdoaWNoIG9uZSB3b3JrZWQgYmVzdC4KCgoKYGBge3IgZWNobyA9IEZ9CnRlbXBfY29lZiA8LSBjb2VmKHRlbXBfbW9kKQp0ZW1wX1NpZ21hIDwtIHZjb3YodGVtcF9tb2QpCgptb2RfZGYgPC0gZGF0YS5mcmFtZShjX29ic2VydmUgPSAtMTQ6NDEpCm1vZF9tYXRyaXggPC0gbW9kZWwubWF0cml4KH5jX29ic2VydmUsIGRhdGEgPSBtb2RfZGYpCgoKQmV0YSA8LSBNQVNTOjptdnJub3JtKDYsIHRlbXBfY29lZiwgdGVtcF9TaWdtYSAqIDUwKQphc190aWJibGUodChCZXRhICUqJSB0KG1vZF9tYXRyaXgpKSkgJT4lCiAgYmluZF9jb2xzKG1vZF9kZiwgLiklPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLWNfb2JzZXJ2ZSklPiUKICBnZ3Bsb3QoYWVzKGNfb2JzZXJ2ZSwgdmFsdWUpKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrICAKICAgIGdlb21fcG9pbnQoZGF0YSA9IHRlbXBfZGYsIAogICAgICAgICAgICAgICBhZXMoeSA9IGZfb2JzZXJ2ZSksIAogICAgICAgICAgICAgICBncm91cCA9IE5BLAogICAgICAgICAgICAgICBjb2xvciA9ICJncmV5ODAiKSsKICAgIGdlb21fbGluZShhZXMoZ3JvdXAgPSBrZXkpLCBjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKGRhdGEgPSB0ZW1wX2RmLCAKICAgICAgICAgICAgICAgIGFlcyhjX29ic2VydmUsIGZfb2JzZXJ2ZSksIAogICAgICAgICAgICAgICAgY29sb3IgPSAncmVkJywKICAgICAgICAgICAgICAgIG1ldGhvZCA9IGxtLCAKICAgICAgICAgICAgICAgIHNlID0gRiwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFQpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrICAKICAgIHRoZW1lX21pbmltYWwoKQoKYGBgCgpIb3dldmVyLCB0aGVyZSBoYXZlIGJlZW4gc29tZSBsb25nIGVzdGFibGlzaGVkIG1ldGhvZHMgZm9yICpzb2x2aW5nKiB0aGlzIHByb2JsZW0sIGF0IGlzLCBmb3IgZmluZGluZyB0aGUgb25lIGFuZCB0cnVseSBiZXN0IEludGVyY2VwdCBhbmQgU2xvcGUgZm9yIGEgZ2l2ZW4gc2V0IG9mIGRhdGEgcG9pbnRzLgoKPGRpdiBjbGFzcyA9ICJib3ggaWRpb20iPgo8c3BhbiBjbGFzcyA9ICdsYWJlbCc+SWRpb208L3NwYW4+CgpUaGlzIGlzbid0IFIgaWRpb20sIGJ1dCBzdGF0cyBpZGlvbS4gSGVyZSBhcmUgc29tZSB0cmFuc2xhdGlvbnMgZm9yIGhvdyBwZW9wbGUgZGVzY3JpYmUgc29sdmluZyB0aGlzIHByb2JsZW0uCgotICphbmFseXRpYyosICpjbG9zZWQgZm9ybSogPSAiV2Ugc29sdmVkIGl0IHdpdGggY29tcGxpY2F0ZWQgbWF0aC4iCi0gKml0ZXJhdGl2ZSosICpzdG9jaGFzdGljKiA9ICJXZSBtYWRlIGEgYnVuY2ggb2YgZ3Vlc3Nlcy4iCgo8L2Rpdj4KCgpGb3IgdGhlIHNha2Ugb2YgZmluaXNoaW5nIHRoZSBpbGx1c3RyYXRpb24sIGhlcmUgaXMgdGhlIHNvbHV0aW9uIHRoYXQgYSBsaW5lYXIgcmVncmVzc2lvbiBmb3VuZCBmb3IgdGhpcyBzYW1wbGUgZGF0YToKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wX21vZApgYGAKClRoZSBtb2RlbCBoYXMgZXN0aW1hdGVkIHRoYXQgdGhlIEludGVyY2VwdCBpcyAkXGFwcHJveCQgYHIgcm91bmQoY29lZih0ZW1wX21vZClbMV0pYCAgYW5kIHRoZSBzbG9wZSBpcyAkXGFwcHJveCQgYHIgcm91bmQoY29lZih0ZW1wX21vZClbMl0sIGRpZ2l0cyA9IDEpYCAuIFRoYXQgaXMgdG8gc2F5LCBiYXNlZCBvbiBvdXIgInNhbXBsZSIsIGl0IHRoaW5rcyAwJiMxNzY7QyA9IGByIHJvdW5kKGNvZWYodGVtcF9tb2QpWzFdKWAmIzE3NjtGLCBhbmQgdGhhdCBldmVyeSAxJiMxNzY7QyBpbmNyZWFzZSBjb3JyZXNwb25kcyB0byBhIGByIHJvdW5kKGNvZWYodGVtcF9tb2QpWzJdLCBkaWdpdHMgPSAxKWAmIzE3NjtGIGluY3JlYXNlLgoKV2UgYXJlIGx1Y2t5IHRvIGtub3cgdGhhdCB0aGlzIGlzLCBzdHJpY3RseSBzcGVha2luZywgd3JvbmcsIGJ1dCB3ZSB3b24ndCB1c3VhbGx5LCBvciB0eXBpY2FsbHksIGJlIGFibGUgdG8gaW4gc3VjaCBhIHNpdHVhdGlvbi4gSG93ZXZlciwgdGhlIGVzdGltYXRlIG9mIGJvdGggdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgaGF2ZSB0aGUgcmlnaHQgKnNpZ24qICh0aGF0IGlzLCBpdCBoYXNuJ3QgZ3Vlc3NlZCB0aGUgaW50ZXJjZXB0IGlzIC0xMCwgb3IgdGhlIHNsb3BlIGdvZXMgdGhlIG90aGVyIHdheSksIGFuZCB0aGV5J3JlIGp1c3QgYWJvdXQgdGhlIHJpZ2h0ICptYWduaXR1ZGUqICh0aGF0IGlzLCBpdCBoYXNuJ3QgZ3Vlc3NlZCB0aGF0IHRoZSBzbG9wZSBpcyBzb21ldGhpbmcgbGlrZSAxMCwgb3IgMTAwKS4KCk5vdywgbGV0J3MgY29uc2lkZXIgaG93IHRoZSBsaW5lYXIgbW9kZWwgaXMgZGVzY3JpYmluZyB0aGUgdmFsdWUgb2YgdGhpcyBoaWdobGlnaHRlZCBkb3QuCmBgYHtyIGVjaG8gPSBGfQpvbmVfZG90IDwtIHRlbXBfZGYgJT4lIAogICAgICAgICAgICAgICAgc2FtcGxlX24oMSkKCgpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKG1ldGhvZCA9ICdsbScsIHNlID0gRiwgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMC41KSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IG9uZV9kb3QsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAzKSsKICAgIHhsYWIoIkNlbGNpdXMiKSsKICAgIHlsYWIoIkZhcmVudGhlaXQiKSsgIAogICAgdGhlbWVfbWluaW1hbCgpCmBgYAoKRmlyc3QsIHlvdSB0YWtlIGl0J3MgdmFsdWUgaW4gQ2VsY2l1cywgYW5kIDxzcGFuIHN0eWxlID0gImNvbG9yOiMyMTZENjU7Zm9udC13ZWlnaHQ6Ym9sZDsiPm11bHRpcGx5IGl0IGJ5IGByIGNvZWYodGVtcF9tb2QpWzJdYDwvc3Bhbj4gKHdoaWNoIGlzIGByIHJvdW5kKG9uZV9kb3QkY19vYnNlcnZlWzFdICogY29lZih0ZW1wX21vZClbMl0sIGRpZ2l0cyA9IDIpYCkKCmBgYHtyIGVjaG8gPSBGfQpvbmVfZG90JG11bHQgPC0gb25lX2RvdCRjX29ic2VydmUgKiBjb2VmKHRlbXBfbW9kKVsyXQpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKG1ldGhvZCA9ICdsbScsIHNlID0gRiwgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMC41KSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IG9uZV9kb3QsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAzKSsKICAgIGdlb21fc2VnbWVudChkYXRhID0gb25lX2RvdCwgCiAgICAgICAgICAgICAgICAgYWVzKHhlbmQgPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlLTAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBtdWx0KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMjE2RDY1IiwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW50aGVpdCIpKyAgCiAgICB0aGVtZV9taW5pbWFsKCkKYGBgCgoKVGhlbiw8c3BhbiBzdHlsZSA9ICJjb2xvcjojQjA4NTM0O2ZvbnQtd2VpZ2h0OmJvbGQ7Ij55b3UgYWRkIGByIGNvZWYodGVtcF9tb2QpWzFdYCB0byBpdDwvc3Bhbj4gKHdoaWNoIGlzIGByIHJvdW5kKChvbmVfZG90JGNfb2JzZXJ2ZVsxXSAqIGNvZWYodGVtcF9tb2QpWzJdKSArIGNvZWYodGVtcF9tb2QpWzFdLCBkaWdpdHMgPSAyKWApCgpgYGB7ciBlY2hvID0gRn0Kb25lX2RvdCRhZGQgPC0gb25lX2RvdCRtdWx0ICsgY29lZih0ZW1wX21vZClbMV0KCmdncGxvdCh0ZW1wX2RmLCBhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk0MCIpKwogICAgc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2UgPSBGLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAwLjUpKwogICAgZ2VvbV9wb2ludChkYXRhID0gb25lX2RvdCwgY29sb3IgPSAncmVkJywgc2l6ZSA9IDMpKwogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZS0wLjUsCiAgICAgICAgICAgICAgICAgICAgIHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiMyMTZENjUiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IGNfb2JzZXJ2ZSArIDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHkgPSBtdWx0LAogICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsKICAgICBnZW9tX3NlZ21lbnQoZGF0YSA9IG9uZV9kb3QsIAogICAgICAgICAgICAgICAgIGFlcyh4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlKzAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IG11bHQsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiNCMDg1MzQiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB4bGFiKCJDZWxjaXVzIikrCiAgICB5bGFiKCJGYXJlbnRoZWl0IikrICAKICAgIHRoZW1lX21pbmltYWwoKQpgYGAKClRoZW4sIHlvdSA8c3BhbiBzdHlsZSA9ICJjb2xvcjojQUMzMzNDO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij5hZGQgdGhlIHJlc2lkdWFsIGVycm9yPC9zcGFuPiB0byBnaXZlIHVzIHRoZSBvYnNlcnZlZCBkYXRhIHBvaW50LgoKYGBge3IgZWNobyA9IEZ9CmdncGxvdCh0ZW1wX2RmLCBhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk0MCIpKwogICAgc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2UgPSBGLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAwLjUpKwogICAgZ2VvbV9wb2ludChkYXRhID0gb25lX2RvdCwgY29sb3IgPSAncmVkJywgc2l6ZSA9IDMpKwogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZS0wLjUsCiAgICAgICAgICAgICAgICAgICAgIHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiMyMTZENjUiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IGNfb2JzZXJ2ZSArIDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHkgPSBtdWx0LAogICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsKICAgICBnZW9tX3NlZ21lbnQoZGF0YSA9IG9uZV9kb3QsIAogICAgICAgICAgICAgICAgIGFlcyh4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlKzAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IG11bHQsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiNCMDg1MzQiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUsCiAgICAgICAgICAgICAgICAgICAgICB4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICAgeSA9IGFkZCwKICAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsgCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgeCA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgeSA9IGFkZCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGZfb2JzZXJ2ZSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiI0FDMzMzQyIsCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW50aGVpdCIpKyAgCiAgICB0aGVtZV9taW5pbWFsKCkKYGBgCgpUaGUgZ2VuZXJpYyBmb3JtdWxhIGZvciBmaW5kaW5nIHRoZSB2YWx1ZSBmb3IgKmFueSogZGF0YSBwb2ludCBpcwoKJCQKRl9pID0gYHIgcm91bmQoY29lZih0ZW1wX21vZClbMV0sIGRpZ2l0cyA9IDEpYCArIChgciByb3VuZChjb2VmKHRlbXBfbW9kKVsyXSwgZGlnaXRzID0gMSlgXHRpbWVzIENfaSkgKyBcZXBzaWxvbl9pLgokJApJbiB0aGlzIGZvcm11bGEgdGhlICRpJCBpcyBjb252ZW50aW9uIGZvciByZWZlcnJpbmcgdG8gc29tZSBnZW5lcmljLCAkaV57dGh9JCBkYXRhIHBvaW50IGFuZCAkXGVwc2lsb24kIGlzIGNvbnZlbnRpb25hbCBmb3IgcmVmZXJyaW5nIHRvIHRoZSByZXNpZHVhbCBlcnJvcnMuCgpTb21lIGFkZGl0aW9uYWwgY29udmVudGlvbnM6CgotIFJlZmVycmluZyB0byB0aGUgb3V0Y29tZSB2YXJpYWJsZSBhcyAkeSQuCi0gUmVmZXJyaW5nIHRvIHRoZSBwcmVkaWN0b3JzIGFzICR4JC4KLSBSZWZlcnJpbmcgdG8gdGhlIHJlbWFpbmluZyBwYXJhbWV0ZXJzIGFzICRcYmV0YSQuCgpTbyB5b3UgbWF5IHNvbWV0aW1lcyBzZWUgcGVvcGxlIHJlZmVycmluZyB0byAkXGJldGFfMCQsIG9yIHRoZSAiYmV0YXMiIGluIGEgbW9kZWwuIFRoZSBmdWxseSBnZW5lcmljIGZvcm11bGEgZm9yIGxpbmVhciByZWdyZXNzaW9uIGlzIHNvbWV0aW1lcyBnaXZlbiBhcwoKCiQkCnlfaSA9IFxiZXRhXzAgKyBcYmV0YSB4X2kgKyBcZXBzaWxvbl9pCiQkCgoKPGRpdiBjbGFzcyA9ICJib3ggaWRpb20iPgo8c3BhbiBjbGFzcyA9ICdsYWJlbCc+SWRpb208L3NwYW4+CgotIFdlIGNhbGwgdGhlICpJbnRlcmNlcHQqIGFuZCAqU2xvcGVzKiB0aGUgKipwYXJhbWV0ZXJzKiogb3IgKipjb2VmZmljaWVudHMqKiBvZiB0aGUgbW9kZWwuCi0gRm9yIGV2ZXJ5IGRhdGEgcG9pbnQsIHRoZSB2YWx1ZSB5b3UgZ2V0IGJ5IG9ubHkgdXNpbmcgdGhlIHNsb3BlcyBhbmQgaW50ZXJjZXB0cyBhcmUgY2FsbGVkIHRoZSAqKmZpdHRlZCB2YWx1ZXMqKiwgYW5kIHRoZXkgYWxsIGxpZSBhbG9uZyB0aGUgbGluZXMgeW91IGRyYXcuCi0gQWxtb3N0IGV2ZXJ5IGRhdGEgcG9pbnQncyBhY3R1YWwgdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gaXRzIGZpdHRlZCB2YWx1ZSwgYW5kIHRoZXNlIGRpZmZlcmVuY2VzIGFyZSBjYWxsZWQgdGhlICoqcmVzaWR1YWxzKiouCgo8L2Rpdj4KCiMjIFVuZGVyc3RhbmRpbmcgY2F0ZWdvcmljYWwgcHJlZGljdG9ycwoKQ2F0ZWdvcmljYWwgdmFyaWFibGVzIGFyZSBuZWNlc3NhcmlsbHkgdHJlYXRlZCBkaWZmZXJlbnRseSBpbiByZWdyZXNzaW9uIG1vZGVscy4KVGhpcyBpcyBiZWNhdXNlIHdoaWxlIHlvdSBjYW4gbXVsdGlwbHkgbnVtZXJpYyBwcmVkaWN0b3JzIHRvZ2V0aGVyLCB5b3UgY2FuJ3QgbXVsdGlwbHkgNSAkXHRpbWVzJCAiZXhwZXJpbWVudGFsIGNvbmRpdGlvbiIuCgpUbyBpbGx1c3RyYXRlIGhvdyBjYXRlZ29yaWNhbCBwcmVkaWN0b3JzIHdvcmsgaW4gYSBsaW5lYXIgcmVncmVzc2lvbiwgd2UnbGwgdXNlIHNvbWUgZXhhbXBsZSB3ZWF0aGVyIGRhdGEuCkkgcHVsbGVkIHRoaXMgZGF0YSBvZiB0aGUgZGFpbHkgdGVtcGVyYXR1cmUgZnJvbSBbdGhlIFVuaXZlcnNpdHkgb2YgRWRpbmJ1cmdoIEdlb3NjaWVuY2VzIERlcGFydG1lbnQgd2VhdGhlciBzdGF0aW9uXShodHRwczovL3d3dy5lZC5hYy51ay9nZW9zY2llbmNlcy93ZWF0aGVyLXN0YXRpb24vd2VhdGhlci1zdGF0aW9uLWRhdGEpLgoKCmBgYHtyIGVjaG8gPUYsIGV2YWwgPSBGfQp3ZWF0aGVycyA8LSBwYXN0ZSgiaHR0cHM6Ly93d3cuZ2Vvcy5lZC5hYy51ay9+d2VhdGhlci9qY21iX3dzL0pDTUJfIiwgc2VxKDIwMDcsIDIwMTUpLCAiLmNzdiIsIHNlcCA9ICIiKQp3ZWF0aGVyX2xpc3QgPC0gbWFwKHdlYXRoZXJzLCByZWFkLmNzdikKd2VhdGhlcl9kZiA8LSBiaW5kX3Jvd3Mod2VhdGhlcl9saXN0KQpgYGAKYGBge3IgZWNobyA9IEZ9CndlYXRoZXJfZGYgPC0gcmVhZF9jc3YoIi4uL2RhdGEvZWRpbl93ZWF0aGVyLmNzdiIpCmBgYAoKCmBgYHtyIGVjaG8gPSBGfQpsaWJyYXJ5KGx1YnJpZGF0ZSkKd2VhdGhlcl9kZiAlPiUKICBmaWx0ZXIoc3VyZmFjZS50ZW1wZXJhdHVyZS4uQy4gPiAtMjAsCiAgICAgICAgIHN1cmZhY2UudGVtcGVyYXR1cmUuLkMuIDwgNDApJT4lCiAgbXV0YXRlKGRhdGUudGltZSA9IHltZF9obShkYXRlLnRpbWUpLAogICAgICAgICBkYXRlID0gYXMuRGF0ZShkYXRlLnRpbWUpKSAlPiUKICBncm91cF9ieShkYXRlKSU+JQogIHN1bW1hcmlzZSh0ZW1wID0gbWVhbihzdXJmYWNlLnRlbXBlcmF0dXJlLi5DLikpJT4lCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoZGF0ZSwgbGFiZWwgPSBUKSwKICAgICAgICAgc2Vhc29uID0gcmVjb2RlKG1vbnRoLAogICAgICAgICAgICAgICAgICAgICAgICAgSmFuID0gIldpbnRlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICBGZWIgPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgIE1hciA9ICJTcHJpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgQXByID0gIlNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBNYXkgPSAiU3ByaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgIEp1biA9ICJTdW1tZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgSnVsID0gIlN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICBBdWcgPSAiU3VtbWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgIFNlcCA9ICJBdXR1bW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgT2N0ID0gIkF1dHVtbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICBOb3YgPSAiQXV0dW1uIiwKICAgICAgICAgICAgICAgICAgICAgICAgIERlYyA9ICJXaW50ZXIiKSwKICAgICAgICAgc2Vhc29uID0gZmFjdG9yKHNlYXNvbiwgb3JkZXJlZCA9IEYpLAogICAgICAgICBkYXkgPSB5ZGF5KGRhdGUpLAogICAgICAgICB5ZWFyID0geWVhcihkYXRlKSkgLT4gdGVtcHMKYGBgCgpgYGB7ciBlY2hvID0gRn0gCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoc2NhbGVzKQp0ZW1wcyAlPiUgCiAgZmlsdGVyKGlzLmZpbml0ZSh0ZW1wKSkgJT4lCiAgZ3JvdXBfYnkobW9udGgsIHllYXIpJT4lCiAgbXV0YXRlKGV4dHJlbWEgPSAibm8iLAogICAgICAgICBleHRyZW1hID0gaW5zZXQoZXh0cmVtYSwgd2hpY2gubWF4KHRlbXApLCAiaGkiKSwKICAgICAgICAgZXh0cmVtYSA9IGluc2V0KGV4dHJlbWEsIHdoaWNoLm1pbih0ZW1wKSwgImxvIikpLT50ZW1wcwoKZ2dwbG90KHRlbXBzLCBhZXMoZGF0ZSwgdGVtcCkpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSBtdXRlZCgiYmx1ZSIpKSsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZXh0cmVtYSkpKwogICAgc2NhbGVfY29sb3JfbWFudWFsKGxpbWl0cyA9IGMoImhpIiwgIm5vIiwibG8iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwgImdyZXk0MCIsICJibHVlIiksCiAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSAibm9uZSIpKwogICAgeWxhYigiZGFpbHkgYXZlcmFnZSB0ZW1wdXJhdHVyZSIpKwogICAgdGhlbWVfbWluaW1hbCgpCmBgYAoKSW4gb3JkZXIgdG8gZm9jdXMgb24gYSBjYXRlZ29yaWNhbCBlZmZlY3QsIEkndmUgcmVjb2RlZCB0aGUgZGF0ZSB2YXJpYWJsZSBpbnRvICJzZWFzb25zIiBsaWtlIHNvOgoKPGRpdiBzdHlsZSA9ICJ3aWR0aDo1MCU7bWFyZ2luOmF1dG87Ij4KCmBgYHtyIHJlc3VsdHMgPSAnYXNpcycsIGVjaG8gPSBGfQpsaWJyYXJ5KGtuaXRyKQp0ZW1wcyAlPiUgCiAgdW5ncm91cCgpJT4lCiAgY291bnQobW9udGgsIHNlYXNvbikgJT4lCiAgc2VsZWN0KC1uKSU+JQogIGthYmxlKCkKYGBgCjwvZGl2PgoKV2UnbGwgZm9jdXMgb24ganVzdCB0aGUgc3Vic2V0IG9mIDIwMTAgYW5kIDIwMTEsIGJlY2F1c2UgMjAxMCB3YXMgYSBub3RhYmx5IGNvbGQgd2ludGVyLiAKSGVyZSdzIGFsbCBvZiB0aGUgZGF0YSBmb3IgdGhlIGZvdXIgc2Vhc29ucyBmcm9tIDIwMTAgYW5kIDIwMTEuCmBgYHtyIGVjaG8gPSBGfQp0ZW1wcyAlPiUKICBmaWx0ZXIoeWVhciAlaW4lIGMoMjAxMCwgMjAxMSkpIC0+IHRlbXBzX2NvbXAKdGVtcHNfY29tcCAlPiUKZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjIpKSsKICAgIHRoZW1lX21pbmltYWwoKQpgYGAKCldpbnRlciBpcyB0aGUgInJlZmVyZW5jZSBsZXZlbCIsIGZvciB0aGUgc2Vhc29uJ3MgZmFjdG9yLCB3aGljaCB5b3UgY2FuIHNlZSBpZiB5b3UgdXNlIGBsZXZlbHMoKWAuCgpgYGB7cn0KbGV2ZWxzKHRlbXBzX2NvbXAkc2Vhc29uKQpgYGAKCldoZW4gdXNpbmcgdHJlYXRtZW50IGNvbnRyYXN0cywgdGhlIGZpcnN0IGxldmVsIGlzIGFsd2F5cyB0cmVhdGVkIGFzIHRoZSByZWZlcmVuY2UgbGV2ZWwuCgpJZiB3ZSBmaXQgYSBsaW5lYXIgbW9kZWwgdG8gdGhpcyBkYXRhLCB3ZSBnZXQgdGhlIGZvbGxvd2luZyBzb2x1dGlvbjoKYGBge3IgZWNobyA9IEZ9CnNlYXNvbl9tb2RlbCA8LSBsbSh0ZW1wIH4gc2Vhc29uLCAKICAgICAgICAgICAgICAgICAgIGRhdGEgPSB0ZW1wc19jb21wKQpzdW1tYXJ5KHNlYXNvbl9tb2RlbCkKYGBgCgpXZSd2ZSBnb3QgYSBidW5jaCBvZiBwYXJhbWV0ZXIgZXN0aW1hdGVzIHVuZGVyICJFc3RpbWF0ZSIgYW5kIGEgYnVuY2ggb2Ygc2lnbmlmaWNhbnQgcC12YWx1ZXMuCkJ1dCB3aGF0IGRvZXMgaXQgbWVhbiB0byBzYXkgIlRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIFNwcmluZyI/IApBbmQgY2FuIHdlIHNheSBhbnRoaW5nIGFib3V0LCBzYXksIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gU3ByaW5nIGFuZCBBdXR1bW4/CkFwcHJvYWNoIHJlc3VsdHMgdGhhdCBsb29rIGxpa2UgdGhpcyBleGFjdGx5IGxpa2UgeW91IHdvdWxkIGEgcmVncmVzc2lvbiB3aXRoIGNvbnRpbnVvdXMgcHJlZGljdG9yczogdHJ5IHRvIGRyYXcgdGhlIGdyYXBoIGl0IGlzIGEgcmVjaXBlIGZvci4KCldlIHN0YXJ0IHdpdGggdGhlICJJbnRlcmNlcHQiLiAKV2l0aCBjb250aW51b3VzIHByZWRpY3RvcnMsIHRoZSAiaW50ZXJjZXB0IiBpcyB0aGUgeSB2YWx1ZSB3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcyAoYS5rLmEuIHRoZSBwcmVkaWN0ZWQgdmFsdWUgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgd2hlbiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlIGlzIDApLiAKV2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIHRoZXJlIGFyZSBubyBsaW5lcyB0byBkcmF3IHRvIGRlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBvdXRjb21lIGFuZCBwcmVkaWN0b3IsIHNvIGNhbGxpbmcgaXQgYW4gaW50ZXJjZXB0IGlzIG1vcmUgb2YgYSBtZXRhcGhvcmljYWwgaG9sZG92ZXIgb2YgdGhlIGNvbnRpbnVvdXMgY2FzZS4gCgpVbmRlcnN0YW5kIHRoZSAiSW50ZXJjZXB0IiBmb3IgY2F0ZWdvcmljYWwgcHJlZGljdG9ycyB0byBiZSAqKnRoZSBwcmVkaWN0ZWQgYXZlcmFnZSBvZiB0aGUgcmV2ZXJlbmNlIGxldmVsKiouCkZvciB0aGUgc2Vhc29ucyBtb2RlbCwgdGhlIGludGVyY2VwdCBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYCwgbWVhbmluZyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2Ugd2ludGVyIHRlbXBlcmF0dXJlIGluIEVkaW5idXJnaCBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYAoKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wc19jb21wICU+JQogIGdyb3VwX2J5KHNlYXNvbiklPiUKICBzdW1tYXJpc2UodGVtcCA9IG1lYW4odGVtcCkpLT50ZW1wX2NvbXBfbWVhbnMKCnRlbXBfY29tcF92ZWMgPC0gdGVtcF9jb21wX21lYW5zJHRlbXAKbmFtZXModGVtcF9jb21wX3ZlYykgPC0gdGVtcF9jb21wX21lYW5zJHNlYXNvbgp0ZW1wX2NvZWYgPC0gY29lZihzZWFzb25fbW9kZWwpCm5hbWVzKHRlbXBfY29lZikgPC0gdGVtcF9jb21wX21lYW5zJHNlYXNvbgp0ZW1wX3JhbmdlIDwtIHJhbmdlKHRlbXBzX2NvbXAkdGVtcCkKCmBgYAoKCmBgYHtyIGVjaG89IEZ9CnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJXaW50ZXIiLCB5PTAsIHllbmQgPSB0ZW1wKSwgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjUsIHkgPSAxLjUsIGxhYmVsID0gcGFzdGUwKCJpbnRlcmNlcHQ9Iixyb3VuZCh0ZW1wLCBkaWdpdHMgPSAxKSkpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siV2ludGVyIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIHhsaW0oIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIiwgIkF1dHVtbiIpKwogICAgeWxpbSh0ZW1wX3JhbmdlWzFdLCB0ZW1wX3JhbmdlWzJdKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpOZXh0LCB3ZSBtb3ZlIHRvIHRoZSB0aGUgYFNwcmluZ2AgZWZmZWN0LgpNb2RlbCBlc3RpbWF0ZXMgYSBTcHJpbmcgZWZmZWN0IG9mIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsyXSwgZGlnaXRzID0gMilgLgpUaGlzIGlzICpub3QqIHRoZSBlc3RpbWF0ZWQgdGVtcGVyYXR1cmUgb2YgRWRpbmJ1cmdoIGluIHNwcmluZy4gVGhpcyBpcyAqKmhvdyBkaWZmZXJlbnQgdGhlIFNwcmluZyB0ZW1wZXJhdHVyZSBpcyBmcm9tIHRoZSBXaW50ZXIgdGVtcGVyYXR1cmUqKi4gCk1lYW5pbmcgdG8gZ2V0IHRoZSBlc3RpbWF0ZWQgU3ByaW5nIHRlbXBlcmF0dXJlIGZyb20gdGhlIG1vZGVsIHdlIG5lZWQgdG8gYWRkIHRoZSBTcHJpbmcgZWZmZWN0IHRvIHRoZSBpbnRlcmNlcHQgKGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsxXSwgZGlnaXRzID0gMilgICsgYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzJdLCBkaWdpdHMgPSAyKWAgPSBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMl0sIGRpZ2l0cyA9IDIpICtyb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpIGApCgoKYGBge3IgZWNobyA9IEZ9CnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IHRlbXBfY29tcF9tZWFucyAlPiUgZmlsdGVyKHNlYXNvbiA9PSAiU3ByaW5nIikpKwogICAgZ2VvbV9zdGVwKGRhdGE9IHRlbXBfY29tcF9tZWFucyAlPiUgZmlsdGVyKHNlYXNvbiAlaW4lIGMoIldpbnRlciIsICJTcHJpbmciKSksIAogICAgICAgICAgICAgIGFlcyhncm91cCA9IDEpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJXaW50ZXIiLCB5PTAsIHllbmQgPSB0ZW1wKSwgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJTcHJpbmciLCAKICAgICAgICAgICAgICAgICAgICAgeCA9ICJTcHJpbmciLAogICAgICAgICAgICAgICAgICAgICB5ID0gdGVtcF9jb21wX3ZlY1siV2ludGVyIl0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSB0ZW1wX2NvbXBfdmVjWyJTcHJpbmciXSksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siV2ludGVyIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiU3ByaW5nIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siU3ByaW5nIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siU3ByaW5nIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjQsIHkgPSAxLjUsIGxhYmVsID0gcGFzdGUwKCJpbnRlcmNlcHQ9Iixyb3VuZCh0ZW1wLCBkaWdpdHMgPSAxKSkpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjQsIHkgPSA1LCBsYWJlbCA9IHBhc3RlMCgic3ByaW5nPSsiLHJvdW5kKHRlbXBfY29lZlsiU3ByaW5nIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgeGxpbSgiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikrCiAgICB5bGltKHRlbXBfcmFuZ2VbMV0sIHRlbXBfcmFuZ2VbMl0pKwogICAgdGhlbWVfYncoKQpgYGAKCk5leHQgdXAgaXMgdGhlIFN1bW1lciBlZmZlY3QsIHdoaWNoIHRoZSBtb2RlbCBlc3RpbWF0ZXMgaXMgIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVszXSwgZGlnaXRzID0gMilgLiAKQWdhaW4sIHRoaXMgaXMgKm5vdCogdGhlIGVzdGltYXRlZCB0ZW1wZXJhdHVyZSBpbiB0aGUgc3VtbWVyLiAKVGhpcyBpcyAqaG93IGRpZmZlcmVudCBTdW1tZXIgaXMgZXN0aW1hdGVkIHRvIGJlIGZyb20gdGhlIEludGVyY2VwdCAoV2ludGVyKSouIApUbyBnZXQgdGhlIGVzdGltYXRlZCBTdW1tZXIgdGVtcGVyYXR1cmUgZnJvbSB0aGUgbW9kZWwgd2UgbmVlZCB0byBhZGQgdGhlIFN1bW1lciBlZmZlY3QgdG8gdGhlIGludGVyY2VwdCAoYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzFdLCBkaWdpdHMgPSAyKWAgKyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbM10sIGRpZ2l0cyA9IDIpYCA9IGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVszXSwgZGlnaXRzID0gMikgK3JvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsxXSwgZGlnaXRzID0gMikgYCkuCgoKCgpgYGB7ciBlY2hvID0gRn0KdGVtcF9jb21wX21lYW5zJT4lCiAgZmlsdGVyKHNlYXNvbiAlaW4lIGMoIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIikpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc3RlcChkYXRhPSB0ZW1wX2NvbXBfbWVhbnMgJT4lIGZpbHRlcihzZWFzb24gJWluJSBjKCJXaW50ZXIiLCAiU3VtbWVyIikpLCAKICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAxKSkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSAiV2ludGVyIiwgeCA9ICJXaW50ZXIiLCB5ID0gMCwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIldpbnRlciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJTdW1tZXIiLCB4ID0gIlN1bW1lciIsIHkgPSB0ZW1wX2NvbXBfdmVjWyJXaW50ZXIiXSwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIlN1bW1lciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IHNlYXNvbiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcCArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKHRlbXAsIGRpZ2l0cyA9IDEpKSkrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS40LCB5ID0gMS41LCBsYWJlbCA9IHBhc3RlMCgiaW50ZXJjZXB0PSIscm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuNCwgeSA9IDEwLCBsYWJlbCA9IHBhc3RlMCgic3VtbWVyPSsiLHJvdW5kKHRlbXBfY29lZlsiU3VtbWVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgeGxpbSgiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikrCiAgICB5bGltKHRlbXBfcmFuZ2VbMV0sIHRlbXBfcmFuZ2VbMl0pKwogICAgdGhlbWVfYncoKQpgYGAKCkFuZCwgd2hhdCBzaG91bGQgc2VlbSBmYW1pbGlhciBieSBub3csIHRoZSBlZmZlY3Qgb2YgQXV0dW1uIGlzIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVs0XSwgZGlnaXRzID0gMilgLCBtZWFuaW5nIEF1dHVtbiBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbNF0sIGRpZ2l0cyA9IDIpYCBkZWdyZWVzIHdhcm1lciB0aGFuIFdpbnRlciwgbWVhbmluZyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgaW4gQXV0dW1uIGlzIChgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYCArIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVs0XSwgZGlnaXRzID0gMilgID0gYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzRdLCBkaWdpdHMgPSAyKSArcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzFdLCBkaWdpdHMgPSAyKSBgKS4KCgoKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uICVpbiUgYygiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc3RlcChkYXRhPSB0ZW1wX2NvbXBfbWVhbnMgJT4lIGZpbHRlcihzZWFzb24gJWluJSBjKCJXaW50ZXIiLCAiQXV0dW1uIikpLCAKICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAxKSkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSAiV2ludGVyIiwgeCA9ICJXaW50ZXIiLCB5ID0gMCwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIldpbnRlciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJBdXR1bW4iLCB4ID0gIkF1dHVtbiIsIHkgPSB0ZW1wX2NvbXBfdmVjWyJXaW50ZXIiXSwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIkF1dHVtbiJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IHNlYXNvbiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcCArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKHRlbXAsIGRpZ2l0cyA9IDEpKSkrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS40LCB5ID0gMS41LCBsYWJlbCA9IHBhc3RlMCgiaW50ZXJjZXB0PSIscm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuNiwgeSA9IDUsIGxhYmVsID0gcGFzdGUwKCJhdXR1bW49KyIscm91bmQodGVtcF9jb2VmWyJBdXR1bW4iXSwgZGlnaXRzID0gMSkpKSkrCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTGV0J3MgcmV2aWV3IHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbCBhZ2FpbjoKCgpgYGB7ciBlY2hvID0gVH0Kc3VtbWFyeShzZWFzb25fbW9kZWwpCmBgYAoKV2UgY2FuIHNheSB0aGUgZm9sbG93aW5nIHRoaW5ncyBhYm91dCB0aGlzIG1vZGVsOgoKLSBUaGUgc2lnbmlmaWNhbnQgYChJbnRlcmNlcHQpYCBlZmZlY3QgbWVhbnMgdGhlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgaW4gV2ludGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCAoZXN0aW1hdGVkIHRvIGJlIDIuNykuCi0gVGhlIHNpZ25pZmljYW50IGBzZWFzb25TcHJpbmdgIGVmZmVjdCBtZWFucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFNwcmluZyBhbmQgV2ludGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCAoU3ByaW5nIGlzIGVzdGltYXRlZCB0byBiZSA1LjMgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKLSBUaGUgc2lnbmlmaWNhbnQgYHNlYXNvblN1bW1lcmAgZWZmZWN0IG1lYW5zIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gU3VtbWVyIGFuZCBXaW50ZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIChTdW1tZXIgaXMgZXN0aW1hdGVkIHRvIGJlIDEwLjcgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKLSBUaGUgc2lnbmlmaWNhbnQgYHNlYXNvbkF1dHVtbmAgZWZmZWN0IG1lYW5zIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gQXV0dW1uIGFuZCBXaW50ZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIChBdXR1bW4gaXMgZXN0aW1hdGVkIHRvIGJlIDcgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKCkFuZCB0aGF0IGlzIHByZXR0eSBtdWNoICphbGwqIHdlIGNhbiBzYXkuIExvb2tpbmcgYXQgdGhlc2UgcmVzdWx0cywgd2UgY2FuIHNheSB0aGF0IFNwcmluZyBpcyBzaWduaWZpY2FudGx5IHdhcm1lciB0aGFuIFdpbnRlciwgYnV0IHdlICpjYW4ndCogc2F5IGFueXRoaW5nIGFib3V0IGEgZ2VuZXJpYyAiZWZmZWN0IG9mIFNwcmluZy4iCkluIGZhY3QsICp3aGF0IHdvdWxkIHdlIG1lYW4gYnkgc3VjaCBhIHRoaW5nIGFueXdheT8qCgpXZSBhbHNvIGNhbid0IHNheSBhbnl0aGluZyBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFueSBvZiB0aGUgb3RoZXIgc2Vhc29ucy4KRm9yIGV4YW1wbGUsIFNwcmluZyBhbmQgQXV0dW1uIGhhdmUgdmVyeSBzaW1pbGFyIGxvb2tpbmcgdGVtcGVyYXR1cmVzICh0aGVpciBkaWZmZXJlbmNlIGZyb20gV2ludGVyIGlzIHZlcnkgc2ltaWxhcikuIFdlIGNhbid0IHNheSBhbnl0aGluZyBhYm91dCB3aGV0aGVyIG9yIG5vdCBTcHJpbmcgaXMgd2FybWVyIG9yIGNvb2xlciB0aGFuIEF1dHVtbi4gCgojIEEgbW9yZSBwcmFjdGljYWwgZXhhbXBsZSAtIFNjYWxpbmcgYW5kIHRyYW5zb3JtaW5nIHByZWRpY3RvcnMKCldlJ3JlIG5vdyBnb2luZyB0byB3YWxrIHRocm91Z2ggYSByZWFsIGV4YW1wbGUgZnJvbSBteSBvd24gcmVzZWFyY2ggaW52b3ZsaW5nIHRoZSB2b3dlbCAvYXkvLiBJbiB0aGlzIGV4YW1wbGUsIHdlJ3JlIGdvaW5nIHRvIGJlIHdhbGtpbmcgdGhyb3VnaCAKCjxkaXYgY2xhc3MgPSAiYm94IGJyZWFrIj4KPHNwYW4gY2xhc3MgPSAiYmlnLWxhYmVsIj5CcmllZiBCYWNrZ3JvdW5kIG9uIC9heS88L3NwYW4+CgpUaGUgRW5nbGlzaCB2b3dlbCAvYXkvIGlzIHRoZSB2b3dlbCBzb3VuZCB0aGF0IGFwcGVhcnMgaW4gdGhlIEVuZ2xpc2ggd29yZHMgKnJpZGUqIGFuZCAqcHJpY2UqLiBJdCBpcyBhICJkaXBodGhvbmciLCBtZWFuaW5nIGl0IGlzIGEgc291bmQgd2l0aCB0d28gZGlmZmVyZW50IGFydGljdWxhdG9yeSB0YXJnZXRzLiBJbiB0aGUgZGlhbGVjdCB0aGlzIGRhdGEgaXMgZHJhd24gZnJvbSwgdGhlIGZpcnN0IHRhcmdldCBpcyBzb21ldGhpbmcgbGlrZSBhIGxvdyBhbmQgYmFjayBbyZFdLCB3aGljaCBhcHBlYXJzIGluIHRoZSB3b3JkcyAqaG90KiBhbmQgKmxvdCosIGFuZCB0aGUgc2Vjb25kIHRhcmdldCBpcyBzb21ldGhpbmcgbGlrZSBhIGhpZ2ggYW5kIGZyb250IFtpOl0sIHdoaWNoIHNob3dzIHVwIGluIHRoZSB3b3JkcyAqZmxlZWNlKiBhbmQgKmhlYXQqLiBXZSdsbCBiZSBmb2N1c2luZyBvbiBqdXN0IHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBkaXBodGhvbmcsIHRoZSB0eXBpY2FsbHkgbG93IGFuZCBiYWNrIHBhcnQuCgpWb3dlbCBzb3VuZHMgY2FuIGJlIGNoYXJhY3Rlcml6ZWQgdXNpbmcgYm90aCBhcnRpY3VsYXRvcnkgYW5kIGFjb3VzdGljIG1lYXN1cmVzLCBhbmQgaXQgaGFzIGJlZW4gZm91bmQgdGhhdCBjZXJ0YWluIGFjb3VzdGljIGZlYXR1cmVzIGNhbiBiZSByZWxpYWJseSBjb3JyZWxhdGVkIHdpdGggdGhlIGFydGljdWxhdG9yeSBwb3NpdGlvbiBvZiB0aGUgdG9uZ3VlIHdoaWxlIHRoZSB2b3dlbHMgYXJlIHByb2R1Y2VkLiBUaGlzIG1lYW5zIHdlIGNhbiBjaGFyYWN0ZXJpemUgc3BlYWtlcnMnIHByb251bmNpYXRpb25zIG9mIHZvd2VsIHNvdW5kcyBmcm9tIGp1c3QgYSByZWNvcmRpbmcgb2YgdGhlaXIgc3BlZWNoLiBJZiB3ZSBleGFtaW5lIGhvdyB0aGVzZSBhY291c3RpYyBwcm9wZXJ0aWVzIG9mIHZvd2VscyBjb3Zhcnkgd2l0aCBzcGVha2VycycgYWdlcyBvciBkYXRlcyBvZiBiaXJ0aCwgd2UgY2FuIGFsc28gZXN0aW1hdGUgaG93IHByb251bmNpYXRpb25zIG9mIHRoZXNlIHZvd2VscyBoYXZlIGNoYW5nZWQgb3ZlciB0aW1lLiAKClRoZXNlIGFjb3VzdGljIHByb3BlcnRpZXMgYXJlIGNhbGxlZCAiZm9ybWFudHMiLCBhbmQgdGhlIGZvcm1hbnQgd2UgYXJlIGdvaW5nIGZvY3VzIG9uIGhlcmUgaXMgIkYxIiwgd2hpY2ggY292YXJpZXMgd2l0aCB0aGUgaGVpZ2h0IG9mIHRoZSB0b25ndWUgaW4gdGhlIG1vdXRoLiBUaGUgaGlnaGVyIEYxLCB0aGUgKmxvd2VyKiBpbiB0aGUgdGhlIG1vdXRoIHRoZSB0b25ndWUgaXMuIEl0J3MgYWxzbyB0aGUgY2FzZSB0aGF0IEYxIHZhbHVlcyBzeXN0ZW1hdGljYWxseSBjb3Zhcnkgd2l0aCB0aGUgbGVuZ3RoIG9mIHNwZWFrZXJzJyB2b2NhbCB0cmFjdHMsIHNvIHdlIGFyZSBhY3R1YWxseSBnb2luZyB0byBiZSBsb29raW5nIGF0ICpub3JtYWxpemVkIEYxKiwgd2hpY2ggYXR0ZW1wdHMgdG8gZmFjdG9yIG91dCB0aGlzIGVmZmVjdC4KPC9kaXY+CgpGb3IgdGhpcyBpbGx1c3RyYXRpb24sIHdlJ3JlIGdvaW5nIHRvIGZpcnN0IGZvY3VzIG9uIHRoZSB2b3dlbCAvYXkvIGJlZm9yZSB2b2ljZWxlc3MgY29uc29uYW50cyAoaS5lLiAvcCwgdCwgaywgZiwgcy8pLgpJbiBQaGlsYWRlbHBoaWEsIHdoZXJlIHRoaXMgZGF0YSBpcyBmcm9tLCAvYXkvIHVuZGVyd2VudCBhIGZhaXJseSBsYXJnZSBzaGlmdCBpbiBpdHMgcHJvbnVuY2lhdGlvbiBhY3Jvc3MgdGhlIDIwdGggY2VudHVyeS4KCmBgYHtyfQpheVRfbWVhbnMgPC0gYXkgJT4lCiAgZmlsdGVyKHBsdF92Y2xhc3MgPT0gImF5MCIgKSU+JSAgIyBnZXQgdGhlIHByZS12b2ljZWxlc3MgdG9rZW5zCiAgbXV0YXRlKGRvYiA9IHllYXIgLSBhZ2UpICU+JSAgICAgIyBjYWxjdWxhdGUgc3BlYWtlcnMnIGRvYgogIGdyb3VwX2J5KGlkc3RyaW5nLCBkb2IpICU+JSAgICAgICMgcHJlcGFyZSB0byBlc3RpbWF0ZSBieS1zcGVha2VyIG1lYW5zCiAgc3VtbWFyaXNlKEYxX24gPSBtZWFuKEYxX24pKSAgICAgIyBtZWFucwpgYGAKCmBgYHtyfQpheVRfbWVhbnMgJT4lCiAgZ2dwbG90KGFlcyhkb2IsIEYxX24pKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpJbiB0aGlzIHBsb3QsIGVhY2ggcG9pbnQgcmVwcmVzZW50cyBvbmUgc3BlYWtlci4KRWFjaCBzcGVha2VyJ3MgYXZlcmFnZSBub3JtYWxpemVkIEYxIHZhbHVlIGlzIHBsb3R0ZWQgYWdhaW5zdCB0aGVpciBkYXRlIG9mIGJpcnRoIChyYW5naW5nIGZyb20gMTg4OSB0byAxOTk4KS4KRml0dGluZyBhIGxpbmVhciBtb2RlbCB0byB0aGlzIGRhdGEgYXBwZWFycyBlYXN5LCBidXQgYWN0dWFsbHkgcG9zZXMgdXMgd2l0aCBpbnRlcnByZXRpdmUgY2hhbGxlbmdlcy4gCgpgYGB7cn0KYXlUX21vZGVsMSA8LSBsbShGMV9uIH4gZG9iLCBkYXRhID0gYXlUX21lYW5zKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGF5VF9tb2RlbDEpCmBgYAoKTGV0J3Mgc29ydCBvdXQgd2hhdCBpcyBiZWluZyByZXBvcnRlZCBoZXJlIGluIHRoaXMgbW9kZWwsIHN0YXJ0aW5nIHdpdGggdGhlIGludGVyY2VwdC4KCmBgYAogICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgMjUuODEwMDk3MCAgMS4wMjMyMTQ2ICAgMjUuMjMgICA8MmUtMTYgKioqCmBgYAoKV2Ugc2VlIGhlcmUgdGhhdCB0aGUgaW50ZXJjZXB0IGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCwgYnV0IHdoYXQgZG9lcyB0aGlzIGludGVyY2VwdCBtZWFuPyAKVGhlIGludGVyY2VwdCBpcyB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIHdoZW4gdGhlIHByZWRpY3RvciBpcyAwLCBtZWFuaW5nIHRoZSBtb2RlbCBpcyBwcmVkaWN0aW5nIGEgdmFsdWUgb2Ygbm9ybWFsaXplZCBGMSBvZiBhYm91dCAyNiBmb3Igc3BlYWtlcnMgYm9ybiBpbiB0aGUgeWVhciAwLgoKCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSAwLCB5ZW5kID0gMjUuOCwgeD0wLCB4ZW5kPTApLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB0aGVtZV9idygpCmBgYAoKVGhpcyBpcyBvYnZpb3VzbHkgcHJvYmxlbWF0aWMuIApGaXJzdCwgdGhpcyBpcyBhICJzaWduaWZpY2FudCIgZWZmZWN0LCBidXQgaXQgZXh0cmFwb2xhdGVzIHNvIGZhciBiZXlvbmQgdGhlIGRhdGEgdGhhdCBpdCdzIGVudGlyZWx5IG1lYW5pbmdsZXNzLiAoTm9ib2R5IHdhcyBzcGVha2luZyAiRW5nbGlzaCIgaW4gdGhlIHllYXIgMC4pClNlY29uZCwgdGhpcyBlc3RpbWF0ZWQgbm9ybWFsaXplZCBGMSB2YWx1ZSBpcyBub3QgYSBwbGF1c2libGUgRjEgdmFsdWUgZm9yICphbnkqIHZvd2VsLiAKSWYgeW91IHdlcmUgdG8gdHJ5IHRvIG1hcCB0aGlzIG9udG8gYW4gYXJ0aWN1bGF0b3J5IHN0cmF0ZWd5LCBzcGVha2VyJ3MgdG9uZ3VlIGJvZGllcyB3b3VsZCBiZSBkb3duIHNvbWV3aGVyZSBhcm91bmQgdGhlaXIgYW5rbGVzLgoKTGV0J3MgYWxzbyBsb29rIGF0IHRoZSBzbG9wZS4gCgpgYGAKICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCmRvYiAgICAgICAgIC0wLjAxMjk3MTAgIDAuMDAwNTI2MiAgLTI0LjY1ICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgbWVhbnMgZm9yIGV2ZXJ5IDEgdW5pdCBpbmNyZWFzZSBpbiBgZG9iYCAoaS5lLiAxIHllYXIpLCB0aGVyZSBpcyBhIGRlY3JlYXNlIG9mIC0wLjAxMyBpbiBub3JtYWxpemVkIEYxLgoKCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSAwLCB5ZW5kID0gMjUuOCwgeD0wLCB4ZW5kPTApLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAyNS44LCBzbG9wZSA9IC0wLjAxMywgY29sb3IgPSAicmVkIikrCiAgICB0aGVtZV9idygpCmBgYAoKCgpJZiB3ZSBpZ25vcmUgdGhlIGNvbWljYWxseSB3ZWlyZCBpbnRlcmNlcHQsIHRoaXMgc2xvcGUgaXMgbGVzcyBwcm9ibGVtYXRpYy4gVGhlIG9uZSBtYWpvciBpc3N1ZSBpbiBpdCBpcyBpdHMgb3ZlcnNwZWNpZmljaXR5LgpUaGlzIHNsb3BlIGlzIGRlZmluZWQgaW4gdGVybXMgb2YgYSBjaGFuZ2UgaW4gMSB5ZWFyIG9mIGRhdGUgb2YgYmlydGgsIGJ1dCBpbiBhbiBpbXBvcnRhbnQgc2Vuc2UgdGhhdCdzIG92ZXIgcHJlY2lzZS4gCldlIHdvdWxkbid0ICpyZWFsbHkqIHdhbnQgdG8gbWFrZSBhbnkgc3Ryb25nIGluZmVyZW5jZXMgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBzcGVha2VycycgYm9ybiBpbiAxOTY5IGFuZCAxOTcwLCBmb3IgZXhhbXBsZS4KCiMjIFJlc2NhbGluZwoKV2UgY2FuIGFkZHJlc3MgdGhlc2UgcHJvYmxlbXMgd2l0aCB0aGUgbW9kZWtsIGJ5ICpyZXNjYWxpbmcqIHRoZSBkYXRlIG9mIGJpcnRoIHByZWRpY3Rvci4KUmVzY2FsaW5nIHByZWRpY3RvcnMgaXMgbm90IG9ubHkgImFsbG93ZWQsIiBpdCBjYW4gYmUgKmNydWNpYWwqIHdoZW4gaXQgY29tZXMgdG8gdHJ5aW5nIHRvIGZpdCBtaXhlZCBlZmZlY3RzIG1vZGVscyEKCjxkaXYgY2xhc3MgPSAiYm94IGlkaW9tIj4KPHNwYW4gY2xhc3MgPSAibGFiZWwiPklkaW9tPC9zcGFuPgoKTm90IHRvIGNvbmZ1c2UgdGhpbmdzIHRvbyBtdWNoLCBidXQgdHJhbnNvcm1hdGlvbnMgeW91IG1ha2UgdG8gcHJlZGljdG9ycyBjYW4gYmUgbHVtcGVkIGludG8gdHdvIGJyb2FkIGNhdGVnb3JpZXM6ICpsaW5lYXIqIGFuZCAqbm9uLWxpbmVhciouIApUaGlzIHVzZSBvZiAibGluZWFyIiBpc24ndCByZWxhdGVkIHRvIGxpbmVhciByZWdyZXNzaW9uIGluIGFueSB3YXkuCkluc3RlYWQsIGl0IGRlc2NyaWJlcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIG9yaWdpbmFsIG1lYXN1cmUgYW5kIHRoZSB0cmFuc2Zvcm1lZCBtZWFzdXJlLgoKIyMjIyBMaW5lYXIgdHJhbnNmb3JtYXRpb25zIGFyZToKCi0gYWRkaXRpb24sIHN1YnRyYWN0aW9uLCBtdWx0aXBsaWNhdGlvbiwgZGl2aXNpb24KClByb29mIGJ5IHNpbXVsYXRpb246CgpgYGB7ciBlY2hvID0gVH0KbGluZWFyX2RmIDwtIGRhdGFfZnJhbWUob3JpZ2luYWwgPSBybm9ybSgxMDAsIG1lYW4gPSA1MCksCiAgICAgICAgICAgICAgICAgICAgICAgIGFkZGl0aW9uID0gb3JpZ2luYWwgKyAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgc3VidHJhY3Rpb24gPSBvcmlnaW5hbCAtIDEwLAogICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsaWNhdGlvbiA9IG9yaWdpbmFsICogMTAsCiAgICAgICAgICAgICAgICAgICAgICAgIGRpdmlzaW9uID0gb3JpZ2luYWwvMTApCmBgYAoKPGRpdiBzdHlsZSA9ICJ3aWR0aDoxMDAlO2Zsb2F0OmxlZnQ7Ij4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7IGZsb2F0OmxlZnQ7IG1hcmdpbjphdXRvOyI+CmBgYHtyIGVjaG8gPSBGLCBmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KGxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLCBhZGRpdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiYWRkaXRpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxzdWJ0cmFjdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgic3VidHJhY3Rpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxtdWx0aXBsaWNhdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgibXVsdGlwbGljYXRpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxkaXZpc2lvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiZGl2aXNpb24iKQpgYGAKPC9kaXY+CjwvZGl2PgoKQW55IGNvbWJpbmF0aW9uIG9mIChvbmx5KSBsaW5lYXIgdHJhbnNmb3JtcyBpcyBhIGxpbmVhciB0cmFuc2Zvcm0uCgojIyMjIE5vbi1saW5lYXIgdHJhbnNmb3JtYXRpb25zIGFyZToKCi0gbG9nYXJpdGhtcyAoYW55IGJhc2UpLCBjb3NpbmUsIHNxdWFyZSByb290LCBldGMuCgpQcm9vZiBieSBzaW11bGF0aW9uOgpgYGB7ciBlY2hvID0gVH0Kbm9ubGluZWFyX2RmIDwtIGRhdGFfZnJhbWUob3JpZ2luYWwgPSBybm9ybSgxMDAsIG1lYW4gPSA1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nX3RlbiA9IGxvZzEwKG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zaW5lID0gY29zKG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3F1YXJlX3Jvb3QgPSBzcXJ0KG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwb25lbnRpYWwgPSBleHAob3JpZ2luYWwpKQpgYGAKCjxkaXYgc3R5bGUgPSAid2lkdGg6MTAwJTtmbG9hdDpsZWZ0OyI+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlOyBmbG9hdDpsZWZ0OyBtYXJnaW46YXV0bzsiPgpgYGB7ciBlY2hvID0gRiwgZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChub25saW5lYXJfZGYsIGFlcyhvcmlnaW5hbCwgbG9nX3RlbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgibG9nMTAiKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChub25saW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxjb3NpbmUpKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX21pbmltYWwoKSsKICAgIGdndGl0bGUoImNvc2luZSIpCmBgYAo8L2Rpdj4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7ZmxvYXQ6bGVmdDttYXJnaW4tbGVmdDoxJTsiPgpgYGB7ciBlY2hvID0gRixmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KG5vbmxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLHNxdWFyZV9yb290KSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJzcXVhcmUgcm9vdCIpCmBgYAo8L2Rpdj4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7ZmxvYXQ6bGVmdDttYXJnaW4tbGVmdDoxJTsiPgpgYGB7ciBlY2hvID0gRixmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KG5vbmxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLGV4cG9uZW50aWFsKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJleHBvbmVudGlhbCIpCmBgYAo8L2Rpdj4KPC9kaXY+Cgo8L2Rpdj4KCklmIHdlIGFwcGx5IG9uZSwgb3IgbWFueSwgKmxpbmVhciogdHJhbnNmb3JtYXRpb25zIHRvIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUsIHdlIHdvbid0IGFmZmVjdCB0aGUgZ29vZG5lc3Mgb2YgZml0IG9mIHRoZSBtb2RlbCwgbm9yIHRoZSBzaWduaWZpY2FuY2Ugb3Igc2lnbiBvZiB0aGF0IHByZWRpY3Rvci4KQnV0IGl0IHdpbGwgY2hhbmdlIHRoZSB3YXkgd2UgKmludGVycHJldCogdGhlIGVmZmVjdHMuCgpUaGVyZSBhcmUgYSBmZXcgZGlmZmVyZW50IGtpbmRzIG9mIHRyYW5zZm9ybWF0aW9ucyB3ZSBjYW4gZG8uIApBIHZlcnkgY29tbW9uIGtpbmQgb2YgdHJhbnNmb3JtYXRpb24gaXMgdG8gKip6LXNjb3JlKiogdGhlIGRhdGEuClRvIHotc2NvcmUgbnVtZXJpYyBkYXRhLCB5b3UgKnN1YnRyYWN0IHRoZSBtZWFuKiBhbmQgKmRpdmlkZSBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uKi4KSGVyZSdzIGhvdyB0aGF0IGxvb2tzIGluIG1hdGhlbWF0aWNhbCBub3RhdGlvbgoKJCQKeiA9IFxmcmFje3gtXG11fXtcc2lnbWF9CiQkCgpXaGVyZSAkXG11JCBpcyB0aGUgbWVhbiBvZiB0aGUgJHgkIGRhdGEsIGFuZCAkXHNpZ21hJCBpcyB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLgpIZXJlJ3MgaG93IHRoYXQgbG9va3MgaW4gcHJhY3RpY2UuIApUaGUgZGF0ZSBvZiBiaXJ0aCBvZiBzcGVha2VycyBoYXMgdGhlIGZvbGxvd2luZyBkaXN0cmlidXRpb24gb2YgZGF0YSwgd2l0aCB0aGUgbWVhbmQgYW5kICRccG0xJCBzdGFuZGFyZCBkZXZpYXRpb24gYW5ub3RhdGVkLgoKCgpgYGB7ciBlY2hvID0gRn0KbWVhbl9kb2IgPC0gbWVhbihheVRfbWVhbnMkZG9iKQpzZF9kb2IgPC0gc2QoYXlUX21lYW5zJGRvYikKZ2dwbG90KGF5VF9tZWFucywgYWVzKGRvYikpKwogICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5NTAiKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW5fZG9iKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSBtZWFuX2RvYiwgeSA9IDAuMDA2LCBsYWJlbCA9ICJtZWFuIikpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbl9kb2IgKyBzZF9kb2IsIGxpbmV0eXBlID0gMikrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gbWVhbl9kb2IgKyBzZF9kb2IsIHkgPSAwLjAwNiwgbGFiZWwgPSAiKzEgc2QiKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuX2RvYiAtIHNkX2RvYiwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSBtZWFuX2RvYiAtIHNkX2RvYiwgeSA9IDAuMDA2LCBsYWJlbCA9ICItMSBzZCIpKSsgICAgCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJPcmlnaW5hbCBTY2FsZSIpCmBgYAoKCkJ5IHN1YnRyYWN0aW5nIG91dCB0aGUgbWVhbiwgd2UgY2VudGVyIHRoaXMgZGlzdHJpYnV0aW9uIG9uIDAsIGFuZCBieSBkaXZpZGluZyBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLCB3ZSBzaHJpbmsgZG93biB0aGUgZGlzdHJpYnV0aW9uIHNvIHRoYXQgMSBzdGFuZGFyZCBkZXZpYXRpb24gZnJvbSB0aGUgbWVhbiBpcyB0aGUgdmFsdWUgMS4KSGVyZSdzIGhvdyB0aGUgcmVzdWx0IGxvb2tzOgoKCgpgYGB7ciBlY2hvID0gRn0KbWVhbl9kb2IgPC0gbWVhbihheVRfbWVhbnMkZG9iKQpzZF9kb2IgPC0gc2QoYXlUX21lYW5zJGRvYikKCmF5VF9tZWFucyA8LSBheVRfbWVhbnMlPiUKICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSU+JQogICAgICAgICAgICAgICAgbXV0YXRlKGRvYl96ID0gKGRvYi1tZWFuKGRvYikpL3NkKGRvYikpCmdncGxvdChheVRfbWVhbnMsIGFlcyhkb2JfeikpKwogICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5NTAiKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDAsIHkgPSAwLjE1LCBsYWJlbCA9ICJtZWFuIikpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLCB5ID0gMC4xNSwgbGFiZWwgPSAiKzEgc2QiKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAtMSwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAtMSwgeSA9IDAuMTUsIGxhYmVsID0gIi0xIHNkIikpKyAgICAKICAgIHRoZW1lX21pbmltYWwoKSsKICAgIGdndGl0bGUoInotU2NhbGUiKQpgYGAKCgojIyMgV2h5IGlzIHRoaXMgYW4gaW1wcm92ZW1lbnQ/IAoKTGV0J3MgcmUtZml0IHRoZSBtb2RlbCB3aXRoIHRoaXMgdHJhbnNmb3JtZWQgRE9CIHByZWRpY3RvciBhbmQgc2VlOgoKYGBge3J9CmF5VF9tb2RlbDIgPC0gbG0oRjFfbiB+IGRvYl96LCBkYXRhID0gYXlUX21lYW5zKQpzdW1tYXJ5KGF5VF9tb2RlbDIpCmBgYAoKYGBgCiAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KQooSW50ZXJjZXB0KSAgMC41ODg2MiAgICAwLjAxMjA1ICAgNDguODMgICA8MmUtMTYgKioqCmBgYAoKVGhlIGludGVyY2VwdCBpcyB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIG5vcm1hbGl6ZWQgRjEgd2hlbiBgZG9iX3pgIGlzIDAsIHdoaWNoIGlzIHRoZSBtZWFuIG9mIGRvYiwgYHIgcm91bmQobWVhbl9kb2IpYC4KCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk3MCIpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gMCwgeWVuZCA9IGNvZWYoYXlUX21vZGVsMilbMV0sIHg9bWVhbl9kb2IsIHhlbmQ9bWVhbl9kb2IpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB0aGVtZV9idygpCmBgYAoKCmBgYAogICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkKZG9iX3ogICAgICAgLTAuMjk3NjAgICAgMC4wMTIwNyAgLTI0LjY1ICAgPDJlLTE2ICoqKgpgYGAKClRoZSBzbG9wZSB0ZWxscyB1cyBob3cgbXVjaCBub3JtYWxpemVkIEYxIGNoYW5nZXMgZm9yIGV2ZXJ5IGNoYW5nZSBvZiAxIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBkb2IgKGByIHJvdW5kKHNkX2RvYilgIHllYXJzKQoKCkZvciBldmVyeSAxIHN0YW5kYXJkIGRldmlhdGlvbiBzaGlmdCBpbiBkb2IgKGByIHJvdW5kKHNkX2RvYilgIHllYXJzKSwgdGhlcmUgaXMgYSBkZWNyZWFzZSBvZiAwLjMgaW4gbm9ybWFsaXplZCBGMS4KCmBgYHtyIGVjaG8gPSBGfQp6X3N0ZXBfZGYgPC0gZGF0YV9mcmFtZShkb2IgPSBjKG1lYW5fZG9iIC0gc2RfZG9iLCBtZWFuX2RvYiwgbWVhbl9kb2IgKyBzZF9kb2IpLAogICAgICAgICAgICAgICAgICAgICAgICBGMV9uID0gYyhjb2VmKGF5VF9tb2RlbDIpWzFdIC0gY29lZihheVRfbW9kZWwyKVsyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZihheVRfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShjb2VmKGF5VF9tb2RlbDIpKSkpCgoKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk3MCIpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gMCwgeWVuZCA9IGNvZWYoYXlUX21vZGVsMilbMV0sIHg9bWVhbl9kb2IsIHhlbmQ9bWVhbl9kb2IpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICBnZW9tX3N0ZXAoZGF0YSA9IHpfc3RlcF9kZiwgZGlyZWN0aW9uID0gJ3ZoJykrCiAgICBnZW9tX3BvaW50KGRhdGEgPSB6X3N0ZXBfZGYsIGNvbG9yID0gInJlZCIpKwogICAgdGhlbWVfYncoKQpgYGAKClRoZXNlIHZhbHVlcyBvZiB0aGUgaW50ZXJjZXB0IGFuZCBzbG9wZSBhcmUgbW9yZSAqaW50ZXJwcmV0YWJsZSouIAoKIyMjIE90aGVyIHBvc3NpYmxlIHRyYW5zZm9ybWF0aW9ucwoKVGhlIHotc2NvcmUgdHJhbnNmb3JtYXRpb24gaXNuJ3QgdGhlICpvbmx5KiB0cmFuc2Zvcm1hdGlvbiB5b3UgY2FuIHVzZS4gSXQncyBqdXN0IHRoZSBtb3N0IHN0YW5kYXJkIG9uZS4gCkZvciBleGFtcGxlLCBHZWxtYW4gJiBIaWxsICgyMDBYWCkgcmVjb21tZW5kIHVzaW5nIGEgbW9kaWZpZWQgei1zY29yZSB3aGVyZSB5b3UgZGl2aWRlIGJ5ICQyXHRpbWVzXHNpZ21hJAoKJCQKeiA9IFxmcmFje3gtXG11fXsyXHNpZ21hfQokJAoKVGhlIHJlYXNvbiB0aGVzZSBmb3JtdWxhcyB1c2UgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBpcyBiZWNhdXNlIHRoZXkgYXJlIHR3byB0aGVvcnkgbmV1dHJhbCB2YWx1ZXMgdGhhdCBjYW4gYmUgZXN0aW1hdGVkIGZvciBhbnkgc2V0IG9mIG51bWVyaWMgZGF0YS4KSG93ZXZlciwgaXQncyBwb3NzaWJsZSB0aGF0IHRoZXJlIGFyZSBtb3JlIHNlbnNpYmxlIHNjYWxpbmcgZmFjdG9ycyBmb3IgdGhlIGRhdGEgeW91J3JlIHdvcmtpbmcgd2l0aC4KRm9yIGV4YW1wbGUsIGluIG1hbnkgc29jaW9saW5ndWlzdGljIHN0dWRpZXMsIHRoZSB5ZWFyIDE5NjAgaXMgYW4gaW1wb3J0YW50IGluZmxlY3Rpb24gcG9pbnQgZm9yIG1hbnkgY2hhbmdlcy4KQW5kIGByIHJvdW5kKHNkX2RvYilgIHllYXJzIGRvZXNuJ3QgaGF2ZSBhbnkgaW50cmluc2ljIG1lYW5pbmcsIHdoaWxlIHNvbWV0aGluZyBsaWtlIDEwIHllYXJzIGlzIG1vcmUgaW50dWl0aXZlbHkgYWNjZXNzaWJsZSB0byBtb3N0IHJlYWRlcnMgKCJhIGRlY2FkZSIpLgpTbyB3ZSBjb3VsZCBqdXN0IGFzIGVhc2lsbHkgY2hvb3NlIHRoaXMgc2NhbGluZyBmb3JtdWxhIGZvciBkYXRlIG9mIGJpcnRoLgoKCiQkCmRlY2FkZSA9IFxmcmFje3ggLSAxOTYwfXsxMH0KJCQKCiMjIyBBcmUgd2UgcmVhbGx5IGFsbG93ZWQgdG8gZG8gYWxsIHRoaXMgcmVzY2FsaW5nPwoKWWVzLCBidXQsICoqeW91IG11c3QgZXhwbGFpbiB3aGF0IHlvdSBkaWQgaW4gdGhlIHdyaXRlIHVwKiouIEZvciBleGFtcGxlOgoKPiBUaGUgZGF0ZSBvZiBiaXJ0aCBwcmVkaWN0b3Igd2FzIGNlbnRlcmVkIG9uIDE5NjAsIGFuZCBkaXZpZGVkIGJ5IDEwLiBUaGUgMTk2MCB3YXMgY2hvc2VuIGFzIHRoZSBjZW50ZXJpbmcgcG9pbnQgYmVjYXVzZSBvZiBpdHMgaW1wb3J0YW5jZSBpbiBwcmV2aW91cyBzb2Npb2xpbmd1aXN0aWMgc3R1ZGllcy4gRGl2aWRpbmcgZG9iIGJ5IDEwIGdpdmVzIHRoZSByZXN1bHRpbmcgc2xvcGUgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSByYXRlIG9mIGNoYW5nZSBwZXIgZGVjYWRlLgoKCgojIE11bHRpdmFyaWF0ZSBNb2RlbHMgJiBJbnRlcmFjdGlvbnMKCldlJ3JlIHF1aWNrbHkgZ29pbmcgdG8gZ28gb3ZlciBtdWx0aXZhcmlhdGUgbW9kZWxzIChtdWx0aXBsZSBwcmVkaWN0b3JzKSBhbmQgaW50ZXJhY3Rpb25zLgpUaGUgaW1wb3J0YW50IHRoaW5nIHRvIGtlZXAgaW4gbWluZCB3aGVuIGluY2x1ZGluZyBtdWx0aXBsZSBwcmVkaWN0b3IgaXMgdGhhdCB5b3VyIHJlZmVyZW5jZSBsZXZlbCBhbmQgc2NhbGluZyBvZiBlYWNoIHByZWRpY3RvciBpcyBnb2luZyB0byBzdGFydCB0byBtYXR0ZXIgYSAqbG90KiBtb3JlLgoKCiMjIENvbnRpbmlvdXMgYW5kIGNhdGVnb3JpY2FsIHByZWRpY3RvcnMKCkxldCdzIHN0YXJ0IHdpdGggdGhlIC9heS8gZGF0YS4gUHJldmlvdXNseSB3ZSB3ZXJlIGxvb2tpbmcgb25seSBhdCBwcmUtdm9pY2VsZXNzIC9heS8uIEJ1dCBub3cgd2UncmUgZ29pbmcgdG8gbG9vayBhdCBhbGwgL2F5Lywgd2l0aCBlYWNoIHRva2VuIGNvZGVkIGZvciB3aGV0aGVyIGl0J3MgcHJlLXZvaWNlbGVzcywgb3IgZWxzZXdoZXJlLiBUaGlzIGlzIGVuY29kZWQgaW4gdGhlIGBwbHRfdmNsYXNzYCBjb2x1bW4uCgotIGBwbHRfdmNsYXNzYAogICAgLSBgYXkwYCAtIFByZS12b2ljZWxlc3MgL2F5LwogICAgLSBgYXlgIC0gQWxsIG90aGVyIC9heS8uCiAgICAKICAgIApCZWNhdXNlIHdlJ3JlIG5vdCBkZWFsaW5nIHdpdGggbWl4ZWQgZWZmZWN0cyBtb2RlbHMgeWV0LCB3ZSdsbCBmaXJzdCBjYWxjdWxhdGUgYnktc3BlYWtlciBtZWFucy4gSW4gdGhlIHByb2Nlc3MgSSdsbCBiZSByZS1zY2FsaW5nIGRhdGUgb2YgYmlydGggd2l0aCB0d28gZGlmZmVyaW5nIGNlbnRlcmluZyBwb2ludHMsIG9uZSBvbiAxOTAwLCBhbmQgb25lIG9uIDE5NjAuCgoKYGBge3J9CmF5X21lYW5zIDwtIGF5ICU+JQogICAgICAgICAgICAgIG11dGF0ZShkb2IgPSB5ZWFyLWFnZSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoaWRzdHJpbmcsIGRvYiwgcGx0X3ZjbGFzcykgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXNlKEYxX24gPSBtZWFuKEYxX24pKSU+JQogICAgICAgICAgICAgIG11dGF0ZShkZWNhZGVfMTkwMCA9IChkb2IgLSAxOTAwKS8xMCwKICAgICAgICAgICAgICAgICAgICAgZGVjYWRlXzE5NjAgPSAoZG9iIC0gMTk2MCkvMTAsCiAgICAgICAgICAgICAgICAgICAgIHZvaWNpbmcgPSBmYWN0b3IocmVjb2RlKHBsdF92Y2xhc3MsIGF5MCA9ICJ2b2ljZWxlc3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheSA9ICJlbHNlIikpLAogICAgICAgICAgICAgICAgICAgICB2b2ljaW5nID0gcmVsZXZlbCh2b2ljaW5nLCAiZWxzZSIpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfYncoKQpgYGAKCiMjIFR3byBwcmVkaWN0b3JzLCBubyBpbnRlcmFjdGlvbnMKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBhICpiaWcqIGRpZmZlcmVuY2UgYmV0d2VlbiBwcmUtdm9pY2VsZXNzIGFuZCBlbHNld2hlcmUgL2F5Ly4gTGV0J3Mgc3RhcnQgYnVpbGRpbmcgdXAgdGhlIG1vZGVsIHRoZW4KCgpgYGB7cn0KYXlfbW9kZWwxIDwtIGxtKEYxX24gfiBkZWNhZGVfMTkwMCArIHZvaWNpbmcsIGRhdGEgPSBheV9tZWFucykKYGBgCgpgYGB7cn0Kc3VtbWFyeShheV9tb2RlbDEpCmBgYAoKCkxldCdzIHdhbGsgdGhyb3VnaCB0aGUgZWZmZWN0cyBieSBkcmF3aW5nIHRoZSBncmFwaCB0aGF0IHRoaXMgbW9kZWwgaXMgYSByZWNpcGUgZm9yLiBGaXJzdCwgd2UgaGF2ZSB0aGUgSW50ZXJjZXB0LgoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgICAgICAgMS41Njc1NzcgICAwLjAyMDg2MiAgIDc1LjE0ICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgaXMgdGhlIGVzdGltYXRlZCBhdmVyYWdlIHZhbHVlIG9mIG5vcm1hbGl6ZWQgRjEgZm9yIHdoZW4gKmFsbCBwcmVkaWN0b3JzIGFyZSAwLiogClRoYXQgbWVhbnMgdGhpcyBpcyB0aGUgcHJlZGljdGVkIGludGVyY2VwdCB3aGVuIHRoZSBjZW50ZXJlZCBkb2IgaXMgMCAoMTkwMCksIGZvciB0aGUgKnJlZmVyZW5jZSBsZXZlbCogKGVsc2V3aGVyZSAvYXkvKQoKCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCB4ZW5kID0gMTkwMCwgeSA9IDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYpKwogICAgdGhlbWVfYncoKQpgYGAKCk5leHQgdGhlcmUncyB0aGUgc2xvcGU6IAoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgICAgICAgMS41Njc1NzcgICAwLjAyMDg2MiAgIDc1LjE0ICAgPDJlLTE2ICoqKgpgYGAKClRoZXJlJ3MgYSBmZXcgZGlmZmVyZW50IHdheXMgd2UgY291bGQgY29uc3RydWUgdGhpcyBzbG9wZS4gVGhlIHZhbHVlIGlzIHRoZSByYXRlIG9mIGNoYW5nZSBwZXIgZGVjYWRlLCBhbmQgd2UnbGwgaW50ZXJwcmV0IHRoaXMgYXMgdGhlIHNsb3BlIGZvciByZWZlcmVuY2UgbGV2ZWwuCgpgYGB7ciBlY2hvID0gRn0KYmFkbW9kIDwtIGxtKEYxX24gfiBkb2IgKyB2b2ljaW5nLCBkYXRhID0gYXlfbWVhbnMpCgpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCB4ZW5kID0gMTkwMCwgeSA9IDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYpKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IGNvZWYoYmFkbW9kKVsxXSwKICAgICAgICAgICAgICAgIHNsb3BlID0gY29lZihiYWRtb2QpWzJdLAogICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgoKRmluYWxseSwgdGhlcmUncyB0aGUgdm9pY2luZyBwYXJhbWV0ZXIuIAoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKdm9pY2luZ3ZvaWNlbGVzcyAtMC42NDMzNTcgICAwLjAxNzM3NiAgLTM3LjAyICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgdGVsbHMgdXMgaG93IGRpZmZlcmVudCB0aGUgKmludGVyY2VwdCogb2YgdGhlIGxpbmUgZm9yIHByZS12b2ljZWxlc3MgL2F5LyBpcyBmcm9tIGVsc2V3aGVyZSAvYXkvLgpCZWNhdXNlIHdlIGhhdmUgaW5jbHVkZWQgbm8gb3RoZXIgZWZmZWN0cyBvciBpbnRlcmFjdGlvbnMsIHRoZSBtb2RlbCBpcyBhc3N1bWluZyB0aGF0IHRoZSBzbG9wZSBvZiB0aGUgcHJlLXZvaWNlbGVzcyAvYXkvIGlzICppZGVudGljYWwqIHRvIGVsc2V3aGVyZSAvYXkvLgoKCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdICsgY29lZihheV9tb2RlbDEpWzNdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKGF5X21vZGVsMSlbMV0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZClbMV0sCiAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kKVsyXSwKICAgICAgICAgICAgICAgIGNvbG9yID0gImVsc2UiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QpWzFdICsgY29lZihiYWRtb2QpWzNdLAogICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZClbMl0sCiAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIHRoZW1lX2J3KCkKYGBgCgoKTm90ZSwgbG9va2luZyBhIHRoaXMgZ3JhcGgsIHlvdSBjYW4gc2VlIHRoYXQgdGhpcyB2b2ljZWxlc3MgZWZmZWN0IGlzICoqbm90KiogdGhlIGVzdGltYXRlZCBpbnRlcmNlcHQgb2YgcHJlLXZvaWNlbHNzIC9heS8uIEl0IGlzIHRoZSBlc3RpbWF0ZWQgKmRpZmZlcmVuY2UqIGluIGludGVyY2VwdHMgYmV0d2VlbiB0aGVzZSB0d28gbGluZXMuCgojIyMgRXZhbHVhdGluZyB0aGUgbW9kZWwuCgpMZXQncyBsb29rIGF0IHRoZSBtb2RlbCBzdW1tYXJ5IGFnYWluOgoKYGBge3J9CnN1bW1hcnkoYXlfbW9kZWwxKQpgYGAKCklmIHlvdSBvbmx5IGZpdCB0aGlzIG1vZGVsLCBhbmQgZGlkbid0IHBsb3QgYW55IG9mIHRoZSBkYXRhLCB5b3UgbWlnaHQgY29uY2x1ZGU6CgotIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgY2hhbmdlIG92ZXIgZGVjYWRlIGZvciAvYXkvLgotIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIHZvaWNpbmcgb24gL2F5Ly4KCiMjIEluY2x1ZGluZyBpbnRlcmFjdGlvbnMKCkhvd2V2ZXIsIGxvb2tpbmcgYXQgdGhlIHBsb3QsIGl0J3MgY2xlYXIgc29tZXRoaW5nIG1vcmUgY29tcGxpY2F0ZWQgaXMgZ29pbmcgb24uIApOZWl0aGVyIG9mIHRoZSBsaW5lcyBsb29rIGxpa2UgdGhleSdyZSBwYXNzaW5nIHRocm91Z2ggdGhlaXIgcmVsYXRlZCBkYXRhIHBvaW50cyB2ZXJ5IHdlbGwuClRoZXJlIGlzLCBpbiBmYWN0LCBhbiAqaW50ZXJhY3Rpb24qIGJldHdlZW4gdm9pY2luZyBhbmQgZGF0ZSBvZiBiaXJ0aC4gClByZS12b2ljZWxlc3MgL2F5LyBpcyB1bmRlcmdvaW5nIGEgY2hhbmdlLCB3aGlsZSBlbHNld2hlcmUgL2F5LyBpcyBiYXNpY2FsbHkgc3RheWluZyB0aGUgc2FtZS4KV2UgY2FuIGFjY291bnQgZm9yIHRoaXMgYnkgaW5jbHVkaW5nIHRoaXMgaW50ZXJhY3Rpb24gaW4gdGhlIG1vZGVsOgoKCmBgYHtyfQpheV9tb2RlbDIgPC0gbG0oRjFfbiB+IGRlY2FkZV8xOTAwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGF5X21vZGVsMikKYGBgCgpMZXQncyBidWlsZCB1cCB0aGUgZ3JhcGguCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAooSW50ZXJjZXB0KSAgICAgICAgICAgICAgICAgICAxLjMyNjU2NCAgIDAuMDIyMjE5ICA1OS43MDMgIDwgMmUtMTYgKioqCmBgYAoKVGhpcyBpcyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2UgZm9yIHdoZW4gYWxsIHByZWRpdG9ycyBhcmUgMCAoaS5lLiBkb2IgPSAxOTAwLCB2b2ljaW5nID0gZWxzZSkuCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDIpWzFdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJlbHNlIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICB0aGVtZV9idygpCmBgYAoKCmBgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCmRlY2FkZV8xOTAwICAgICAgICAgICAgICAgICAgLTAuMDIxMjc3ICAgMC4wMDQ0NDMgIC00Ljc4OSAyLjA4ZS0wNiAqKioKYGBgCgpUaGlzIGlzIHRoZSBlc3RpbWF0ZWQgc2xvcGUgKmZvciB0aGUgcmVmZXJlbmNlIGxldmVsKiAoaS5lLiB2b2ljaW5nID0gZWxzZSkKCmBgYHtyIGVjaG8gPSBGfQpiYWRtb2QyIDwtIGxtKEYxX24gfiBkb2IgKiB2b2ljaW5nLCBkYXRhID0gYXlfbWVhbnMpCgpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDIpWzFdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJlbHNlIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpOb3csIHdlIGdldCBpbnRvIHRoZSBtb3JlIGNvbXBsaWNhdGVkIGNvZWZmaWNpZW50cy4KCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAp2b2ljaW5ndm9pY2VsZXNzICAgICAgICAgICAgIC0wLjE2MTMyOSAgIDAuMDMxNDIzICAtNS4xMzQgMy43NWUtMDcgKioqCmBgYAoKVGhpcyBpcyBob3cgZGlmZmVyZW50IHRoZSBsaW5lIGZvciBwcmUtdm9pY2VsZXNzIC9heS8gaXMgZnJvbSBlbHNld2hlcmUgL2F5LyAqYXQgdGhlIGludGVyY2VwdCogKGkuZS4gd2hlbiBkb2IgPSAxOTAwKS4KCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fc2VnbWVudChhZXMoeSA9IGNvZWYoYXlfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYoYXlfbW9kZWwyKVsxXSArIGNvZWYoYXlfbW9kZWwyKVszXSwKICAgICAgICAgICAgICAgICAgICAgeCA9IDE5MDAsCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCksCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpGaW5hbGx5LCB3ZSBoYXZlIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3QuCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApkZWNhZGVfMTkwMDp2b2ljaW5ndm9pY2VsZXNzIC0wLjEwODQzMyAgIDAuMDA2MjgzIC0xNy4yNTcgIDwgMmUtMTYgKioqCmBgYAoKVGhpcyBpcyB0aGUgbW9zdCBlYXNpbGx5IG1pc2ludGVycHJldGFibGUgcGFyYW1ldGVyIGluIHRoaXMgbW9kZWwuIApJdCBpcyAqbm90KiB0aGUgZXN0aW1hdGVkIHNsb3BlIG9mIHByZS12b2ljZWxlc3MgL2F5Ly4gSXQgaXMgKmhvdyBkaWZmZXJlbnQqIHByZS12b2ljZWxlc3MgL2F5LydzIHNsb3BlIGlzIGZyb20gZWxzZXdoZXJlIC9heS8uIApUaGF0IGlzLCBpZiB5b3UgZHJldyBhIGxpbmUgcGFyYWxsZWwgdG8gZWxzZXdoZXJlIC9heS8sIHRob3MgaXMgaG93IG11Y2ggeW91J2QgaGF2ZSB0byByb3RhdGUgdGhlIHRoZSBsaW5lIHRvIGdldCBwcmUtdm9pY2VsZXNzIC9heS8ncyBzbG9wZS4KCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fc2VnbWVudChhZXMoeSA9IGNvZWYoYXlfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYoYXlfbW9kZWwyKVsxXSArIGNvZWYoYXlfbW9kZWwyKVszXSwKICAgICAgICAgICAgICAgICAgICAgeCA9IDE5MDAsCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCksCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZDIpWzFdICsgY29lZihheV9tb2RlbDIpWzNdLAogICAgICAgICAgICAgICAgICAgIHNsb3BlID0gY29lZihiYWRtb2QyKVsyXSwKICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSArIGNvZWYoYmFkbW9kMilbM10sCiAgICAgICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZDIpWzJdICsgY29lZihiYWRtb2QyKVs0XSwKICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIHRoZW1lX2J3KCkKYGBgCgojIyMgQmUgY2FyZWZ1bCB0aGlua2luZyBhYm91dCBtb2RlbHMgd2l0aCBpbnRlcmFjdGlvbnMKClRoaXMgaXMgc3VwZXIgaW1wb3J0YW50IHRvIGtlZXAgaW4gbWluZCwgbGV0J3Mgc2F5IHdlIHJhbiB0aGlzIG1vZGVsLCBhbmQgZ290IHRoZSBmb2xsb3dpbmcgY29lZmZpY2llbnRzOgoKYGBgCihJbnRlcmNlcHQpICAgICAgICAgICAgICAgICAgIDEuMzIgICAgKioqCmRlY2FkZV8xOTAwICAgICAgICAgICAgICAgICAgLTEwICAgICAgKioqCnZvaWNpbmd2b2ljZWxlc3MgICAgICAgICAgICAgLTAuMTYgICAgKioqCmRlY2FkZV8xOTAwOnZvaWNpbmd2b2ljZWxlc3MgIDEwICAgICAgKioqCmBgYAoKVGhlIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gZGF0ZSBvZiBiaXJ0aCBhbmQgdm9pY2luZyBoZXJlIHdvdWxkICoqbm90KiogbWVhbiB0aGF0IHRoZXJlIGlzIHNpZ25pZmljYW50IGNoYW5nZSBmb3IgcHJlLXZvaWNlbGVzcyAvYXkvIG92ZXIgdGltZS4gCkl0IG1lYW5zIHRoZXJlIGlzIGEgKipzaWduaWZpY2FudCBkaWZmZXJlbmNlKiogYmV0d2VlbiB0aGUgc2xvcGUgb2YgZWxzZXdoZXJlIC9heS8gYW5kIHByZS12b2ljZWxlc3MgL2F5Ly4gClRoZSBlc3RpbWF0ZWQgc2xvcGUgb2YgZWxzZXdoZXJlIC9heS8gaW4gdGhpcyBmYWtlIG1vZGVsIGlzIC0xMCwgYW5kIGZvciBwcmUtdm9pY2VsZXNzIC9heS8gaXQncyAtMTAgKyAxMCA9IDAhCgpUaGUgb3RoZXIgdGhpbmcgdG8ga2VlcCBpbiBtaW5kIHdpdGggaW50ZXJwcmV0aW5nIHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbCBpcyB0aGF0IHRoZSBgdm9pY2luZ3ZvaWNlbGVzc2AgZWZmZWN0IGlzICpub3QqIGFuIGVzdGltYXRlIG9mICJ0aGUgZWZmZWN0IG9mIHZvaWNpbmcuIgpJdCBpcyB0aGUgZXN0aW1hdGVkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIGxpbmVzICphdCB0aGUgaW50ZXJjZXB0Ki4gCklmIHdlIGNoYW5nZSB3aGVyZSB0aGUgaW50ZXJjZXB0IGlzLCBmb3IgZXhhbXBsZSBieSB1c2luZyBhIGRpZmZlcmVudCBzY2FsaW5nLCB3ZSBhbHNvIGNoYW5nZSB0aGUgdmFsdWUgb2YgdGhpcyBwYXJhbWV0ZXIuIAoKYGBge3J9CnN1bW1hcnkobG0oRjFfbiB+IGRlY2FkZV8xOTAwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKSkKYGBgCgoKYGBge3J9CnN1bW1hcnkobG0oRjFfbiB+IGRlY2FkZV8xOTYwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKSkKYGBgCgpXaXRoIHRoZSBkYXRlIG9mIGJpcnRoIGNlbnRlcmVkIG9uIDE5MDAsIHdlIGdldCBhIHJlbGF0aXZlbHkgd2VhayBlZmZlY3QgKC0wLjE2KS4gCldpdGggdGhlIGRhdGUgb2YgYmlydGggY2VudGVyZWQgb24gMTk2MCwgd2UgZ2V0IGEgbXVjaCBzdHJvbmdlciBlZmZlY3QgKC0wLjgxKS4KVGhhdCdzIGJlY2F1c2UgdGhlcmUgaXMgYSBzdHJvbmcgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGUgZGF0ZSBvZiBiaXJ0aCBhbmQgdm9pY2luZyBjb250ZXh0LCBhbmQgdGhlcmUgaXMgYSBiaWdnZXIgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZXNlIHR3byBsaW5lcyBpbiAxOTYwIHRoYW4gaW4gMTkwMCEKCgpgYGB7ciBlY2hvID0gRn0KYXlfbW9kZWwzIDwtIGxtKEYxX24gfiBkZWNhZGVfMTk2MCAqIHZvaWNpbmcsIGRhdGEgPSBheV9tZWFucykKZ2dwbG90KGF5X21lYW5zLCBhZXMoZG9iLCBGMV9uLCBjb2xvciA9IHZvaWNpbmcpKSsKICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMpKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IGNvZWYoYmFkbW9kMilbMV0sCiAgICAgICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZDIpWzJdLAogICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImVsc2UiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSBjb2VmKGF5X21vZGVsMilbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKGF5X21vZGVsMilbMV0gKyBjb2VmKGF5X21vZGVsMilbM10sCiAgICAgICAgICAgICAgICAgICAgIHggPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTkwMCwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAidm9pY2VsZXNzIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSBjb2VmKGF5X21vZGVsMylbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKGF5X21vZGVsMylbMV0gKyBjb2VmKGF5X21vZGVsMylbM10sCiAgICAgICAgICAgICAgICAgICAgIHggPSAxOTYwLAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTk2MCwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAidm9pY2VsZXNzIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZDIpWzFdICsgY29lZihiYWRtb2QyKVszXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0gKyBjb2VmKGJhZG1vZDIpWzRdLAogICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInZvaWNlbGVzcyIpLAogICAgICAgICAgICAgICAgbGluZXR5cGUgPSAxLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsgIAogICAgdGhlbWVfYncoKQpgYGAKCkl0IGlzLCBpbiBmYWN0LCBtb3JlIHRoYW4gcG9zc2libGUgZm9yIGEgcHJlZGljdG9yIGxpa2UgdGhpcyB0byBoYXZlIGFuIGVzdGltYXRlZCB2YWx1ZSBjbG9zZSB0byAwLCBhbmQgYmUgbm9uLXNpZ25pZmljYW50LCBidXQgZm9yIGl0IHRvIGFjdHVhbGx0eSBtYXR0ZXIgYSAqbG90KiB0byB0aGUgbW9kZWwuCgoqKkxlc3NvbnMqKgoKLSBBbHdheXMgdGhpbmsgY2FyZWZ1bGx5IGFib3V0IHRoZSAqbWVhbmluZyogb2YgcHJlZGljdG9ycyBpbiBhIG1vZGVsIHdpdGggaW50ZXJhY3Rpb25zLgotIEFsd2F5cyB0cnkgdG8gZHJhdyB0aGUgZ3JhcGggb3V0LgotIEFsd2F5cyByZW1lbWJlciB0aGUgcGFyYW1ldGVycyBhcmUgZXN0aW1hdGVzIG9mIHRoZSAqZGlmZmVyZW5jZSogZnJvbSB0aGUgcmVmZXJlbmNlIGxldmVscy4KLSBOb24tc2lnbmlmaWNhbnQgIT0gbm90IGltcG9ydGFudC4KCgojIyBDYXRlZ29yaWNhbCBpbnRlcmFjdGlvbnMuCgpXZSdsbCByZXR1cm4gdG8gdGhlIHdlYXRoZXIgZGF0YSB0byBleGFtaW5lIHRoZSBpbnRlcnByZXRhdGlvbiBvZiBjYXRlZ29yaWNhbCBpbnRlcmFjdGlvbnMuIApXZSdsbCBiZSB1c2luZyBzZWFzb24gYW5kIGEgY2F0ZWdvcmljYWwgY29kaW5nIG9mIHllYXIuCgpgYGB7cn0KdGVtcHNfY29tcCA8LSB0ZW1wc19jb21wICU+JQogICAgICAgICAgICAgICAgICBtdXRhdGUoeWVhcl9mYWN0b3IgPSBmYWN0b3IoeWVhcikpCmBgYAoKRml0dGluZyB0aGUgbW9kZWwgaXMgc3RyYWlnaHQgZm9yd2FyZC4KYGBge3J9CnRlbXBzX21vZGVsIDwtIGxtKHRlbXAgfiBzZWFzb24gKiB5ZWFyX2ZhY3RvciwgZGF0YSA9IHRlbXBzX2NvbXApCmBgYAoKYGBge3J9CnN1bW1hcnkodGVtcHNfbW9kZWwpCmBgYAoKVGhlcmUncyBhIGxvdCBnb2luZyBvbiBoZXJlLCBhbmQgaXQgaXMgdmVyeSBlYXN5IHRvIG1pc2ludGVycHJldCB0aGUgcmVzdWx0cyBpZiB5b3UgZG9uJ3QgdHJ5IHRvIGRyYXcgb3V0IHRoZSBncmFwaC4gCldlJ2xsIHRha2UgdGhlIGNvZWZmaWNpZW50cyBpbiBiYXRjaGVzLiBGaXJzdCwgdGhlcmUgaXMgdGhlICJpbnRlcmNlcHQuIgoKYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAooSW50ZXJjZXB0KSAgICAgICAgICAgICAgICAgICAgMS4yMTUxICAgICAwLjMwOTIgICAzLjkyOSA5LjM3ZS0wNSAqKioKYGBgCgpUaGlzIGlzIHRoZSBlc3RpbWF0ZWQgYXZlcmFnZSB0ZW1wZXJhdHVyZSBmb3IgdGhlIHJlZmVyZW5jZXMgbGV2ZWxzLCB0aGF0IGlzLCBmb3Igc2Vhc29uID0gV2ludGVyLCB5ZWFyID0gMjAxMC4KCgpgYGB7ciBlY2hvPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAwLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZih0ZW1wc19tb2RlbClbMV0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTmV4dCwgdGhlcmUgYXJlIHRoZSBzZWFzb24gZWZmZWN0cy4KYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApzZWFzb25TcHJpbmcgICAgICAgICAgICAgICAgICAgNi4xNjYxICAgICAwLjQ2MDMgIDEzLjM5NSAgPCAyZS0xNiAqKioKc2Vhc29uU3VtbWVyICAgICAgICAgICAgICAgICAgMTIuNzQ3MiAgICAgMC40Mzg1ICAyOS4wNjcgIDwgMmUtMTYgKioqCnNlYXNvbkF1dHVtbiAgICAgICAgICAgICAgICAgICA3LjMxNTAgICAgIDAuNDQ1MSAgMTYuNDM2ICA8IDJlLTE2ICoqKgpgYGAKClJlY2FsbCwgdGhlc2UgYXJlIHRoZSBlc3RpbWF0ZWQgKmRpZmZlcmVuY2VzKiBiZXR3ZWVuIFdpbnRlciBhbmQgdGhlIG5hbWVkIHNlYXNvbi4gQnV0IGJlY2F1c2UgdGhlcmUgaXMgYW4gaW50ZXJhY3Rpb24gZWZmZWN0IGJldHdlZW4gc2Vhc29uIGFuZCB5ZWFyLCB0aGVzZSB2YWx1ZXMgYXJlIGV2ZW4gbW9yZSBzcGVjaWZpYzogdGhlc2UgYXJlIHRoZSBlc3RpbWF0ZWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIG9mIHRoZXNlIG5hbWVkIHNlYXNvbnMgYW5kIFdpbnRlciAqKmluIDIwMTAqKiwgYmVjYXVzZSAyMDEwIGlzIHRoZSByZWZlcmVuY2UgbGV2ZWwgZm9yIHllYXIuCgoKCmBgYHtyIGVjaG89IEZ9CgpzcHJpbmcgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMS45KSwKICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKSkKc3VtbWVyIDwtIGRhdGEuZnJhbWUoc2Vhc29uID0gYygwLjksIDIuOSksCiAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBjKGNvZWYodGVtcHNfbW9kZWwpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSkpCmZhbGwgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMy45KSwKICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKSkKCnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21fYmxhbmsoKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fc2VnbWVudChhZXMoeCA9IDAuOSwKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDAuOSwKICAgICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICBnZW9tX2xhYmVsKGFlcyh4ID0gMC45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKICAgIGdlb21fc3RlcChkYXRhID0gc3ByaW5nLCBncm91cCA9IDEpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMS45LAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMS45LAogICAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDEuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDIuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzNdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAyLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAyLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAzLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAzLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNF0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAgCiAgICBnZW9tX3N0ZXAoZGF0YSA9IHN1bW1lciwgZ3JvdXAgPSAxKSsgIAogICAgZ2VvbV9zdGVwKGRhdGEgPSBmYWxsLCBncm91cCA9IDEpKyAgCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTmV4dCBpcyB0aGUgeWVhciBlZmZlY3QKCmBgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKeWVhcl9mYWN0b3IyMDExICAgICAgICAgICAgICAgIDMuMDI2NCAgICAgMC40MzczICAgNi45MjAgMS4wM2UtMTEgKioqCmBgYAoKQWdhaW4sIGJlY2F1c2UgdGhlcmUgaXMgYW4gaW50ZXJhY3Rpb24gZWZmZWN0IGJldHdlZW4gc2Vhc29uIGFuZCB5ZWFyLCB0aGlzIGlzIGVzdGltYXRlZCBkaWZmZXJlbmNlIGJldHdlZW4gV2ludGVyIDIwMTAgYW5kIFdpbnRlciAyMDExLiBJJ20gZHJhd2luZyB0aGlzIG9uIHRoZSBncmFwaCBmb3Igd2ludGVyIGluIGEgc29saWQgbGluZSwgYW5kIGZvciBhbGwgb2YgdGhlIG90aGVyIHNlYXNvbnMgaW4gYSBkYXNoZWQgbGluZS4gQXMgd2lsbCBiZSBtYWRlIGNsZWFyIGluIGEgbW9tZW50LCB0aGlzIGlzIGlzIGJlY2F1c2UgdGhlIGludGVyYWN0aW9uIGVmZmVjdHMgY2FuIG9ubHkgYmUgaW50ZXJwcmV0ZWQgaW4gcmVsYXRpb24gdG8gdGhlc2UgZGFzaGVkIGxpbmVzLgoKYGBge3IgZWNobz0gRn0Kd2ludGVyX3llYXIgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMS4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wID0gYyhjb2VmKHRlbXBzX21vZGVsKVsxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSkpCnNwcmluZ195ZWFyIDwtIGRhdGEuZnJhbWUoc2Vhc29uID0gYygxLjksIDIuMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgY29lZih0ZW1wc19tb2RlbClbNV0pKQpzdW1tZXJfeWVhciA8LSBkYXRhLmZyYW1lKHNlYXNvbiA9IGMoMi45LCAzLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBjKGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGNvZWYodGVtcHNfbW9kZWwpWzVdKSkKYXV0dW1uX3llYXIgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDMuOSwgNC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wID0gYyhjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBjb2VmKHRlbXBzX21vZGVsKVs1XSkpCgp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgZ2VvbV9zdGVwKGRhdGEgPSB3aW50ZXJfeWVhcikrCiAgZ2VvbV9zdGVwKGRhdGEgPSBzcHJpbmdfeWVhciwgbGluZXR5cGUgPSAyKSsgIAogIGdlb21fc3RlcChkYXRhID0gc3VtbWVyX3llYXIsIGxpbmV0eXBlID0gMikrICAKICBnZW9tX3N0ZXAoZGF0YSA9IGF1dHVtbl95ZWFyLCBsaW5ldHlwZSA9IDIpKyAgICAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjEsIHhlbmQgPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNV0pLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogIGdlb21fbGFiZWwoYWVzKHggPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAgIAogIGdlb21fbGFiZWwoYWVzKHggPSAwLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAzLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIHhsaW0oIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIiwgIkF1dHVtbiIpKwogICAgeWxpbSh0ZW1wX3JhbmdlWzFdLCB0ZW1wX3JhbmdlWzJdKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpGaW5hbGx5LCB0aGVyZSBhcmUgdGhlIGludGVyYXRpb24gdGVybXMhCgoKYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApzZWFzb25TcHJpbmc6eWVhcl9mYWN0b3IyMDExICAtMS44NzA3ICAgICAwLjYzMzMgIC0yLjk1NCAgMC4wMDMyNCAqKiAKc2Vhc29uU3VtbWVyOnllYXJfZmFjdG9yMjAxMSAgLTQuMDIxNSAgICAgMC42MTc2ICAtNi41MTEgMS40M2UtMTAgKioqCnNlYXNvbkF1dHVtbjp5ZWFyX2ZhY3RvcjIwMTEgIC0wLjcyNzAgICAgIDAuNjIzMSAgLTEuMTY3ICAwLjI0Mzc1ICAgIApgYGAKClRoZSBlZmZlY3Qgb2YgeWVhciBpbiB0aGUgbW9kZWwgd2FzIGFib3V0IDMsIG1lYW5pbmcgV2ludGVyIDIwMTEgd2FzIDMgZGVncmVlcyB3YXJtZXIgdGhhbiBXaW50ZXIgMjAxMC4gSWYgd2UgbG9vayBhdCB0aGUgU3ByaW5nOlllYXIgaW50ZXJhY3Rpb24gaGVyZSwgaXQgaGFzIGEgdmFsdWUgb2YgLTEuOSwgbWVhbmluZyBTcHJpbmcgMjAxMSB3YXMgMy0xLjkgPSBgciAzLTEuOWAgZGVncmVlIHdhcm1lciB0aGFuIFNwcmluZyAyMDEwLgoKVGhhdCBpcywgdGhlc2UgaW50ZXJhY3Rpb24gdGVybXMgYXJlIHRlbGxpbmcgdXMgaG93IGRpZmZlcmVudCB0aGUgeWVhciBlZmZlY3QgZm9yIGVhY2ggc2Vhc29uIGlzIGZyb20gdGhlIHllYXIgZWZmZWN0IGZvciBXaW50ZXIsIG91ciByZWZlcmVuY2UgbGV2ZWwuIEp1c3QgYmVjYXVzZSBTcHJpbmc6MjAxMSBoYXMgYSBzaWduaWZpY2FudCBuZWdhdGl2ZSB2YWx1ZSBkb2Vzbid0IG1lYW4gU3ByaW5nIDIwMTEgd2FzIGNvbGRlciB0aGFuIFNwcmluZyAyMDEwISBJdCBqdXN0IG1lYW5zIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBTcHJpbmcgMjAxMCBhbmQgU3ByaW5nIDIwMTEgd2FzIG5vdCBhcyBiaWcgYXMgdGhhdCBiZXR3ZWVuIFdpbnRlciAyMDEwIGFuZCBXaW50ZXIgMjAxMSEKClRoZSBzaWduaWZpY2FudCBTcHJpbmc6MjAxMSBlZmZlY3QgYWxzbyAqKmRvZXMgbm90IG1lYW4qKiB0aGF0IFNwcmluZyAyMDExIHdhcyBhIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRlbXBlcmF0dXJlIHRoYW4gU3ByaW5nIDIwMTAhCgpgYGB7ciBlY2hvPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgZ2VvbV9zdGVwKGRhdGEgPSB3aW50ZXJfeWVhcikrCiAgZ2VvbV9zdGVwKGRhdGEgPSBzcHJpbmdfeWVhciwgbGluZXR5cGUgPSAyKSsgIAogIGdlb21fc3RlcChkYXRhID0gc3VtbWVyX3llYXIsIGxpbmV0eXBlID0gMikrICAKICBnZW9tX3N0ZXAoZGF0YSA9IGF1dHVtbl95ZWFyLCBsaW5ldHlwZSA9IDIpKyAgICAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjEsIHhlbmQgPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNV0pLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogIGdlb21fbGFiZWwoYWVzKHggPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAKCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMi4xLCB4ZW5kID0gMi4xLAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0gKyBjb2VmKHRlbXBzX21vZGVsKVs2XSksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzZdLTEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAgIAogIAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMy4xLCB4ZW5kID0gMy4xLAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0gKyBjb2VmKHRlbXBzX21vZGVsKVs3XSksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAzLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzddLTEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKCgogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSA0LjEsIHhlbmQgPSA0LjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzhdKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDQuMSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWYodGVtcHNfbW9kZWwpWzVdICsgY29lZih0ZW1wc19tb2RlbClbOF0tMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTEiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAgIAogICAgCiAgCiAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMC45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdLAogICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiMjAxMCIpLAogICAgICAgICAgICAgICBzaXplID0gMi41KSsgICAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMi45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMy45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNF0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKIyMgTmV4dCBXZWVrCgotIEludHJvZHVjaW5nIE1peGVkIEVmZmVjdHMgTW9kZWxzCg==